如何填充具有另一个联接的子列表

时间:2018-02-18 09:48:53

标签: c# linq

我想通过linq join填充我的子列表。怎么做到这一点?下面列出了我无法弄清楚的代码。

var model = (from personel in db.Personels
     where personel.ID == id
     from contact in personel.ContactTypes 

     join contactType in db.ContactTypes on contact.ContactTypeId equals contactType.ID

     select new PersonelWithContactListDto
     {
         PersonelName = personel.PersonelName,
         PersonelLastname = personel.PersonelLastname,
         PersonelPrivateNo = personel.PersonelPrivateNo,
         // here how to select my sublist. If I leverage
         // let = dbobjects.DefaultIfEmpty() then I am no 
         // longer able to specify contactType from another table.
         //Contact = contacts.Select(x => new ContactListDto
         //{
         //    Value = x.Value,
         //    ContactType = contactType.Value,
         //    ID = x.ID
         //}).ToList()
     }).FirstOrDefault();

这是我的dto课程。

public class PersonelWithContactListDto
{
    public string PersonelName { get; set; }

    public string PersonelLastname { get; set; }

    public int PersonelPrivateNo { get; set; }

    public IList<ContactListDto> Contacts { get; set; }
}

以下是我的关键地图的域类。

它的人员类

public class Personel
{
    public int ID { get; set; }

    [Required]
    public string PersonelName { get; set; }

    [Required]
    public string PersonelSurname { get; set; }

    [Required]
    [Index(IsUnique = true)]
    public int PersonelPrivateNo { get; set; }

    public virtual ICollection<Contact> Contacts { get; set; }
}

每个人可能有多个的联系课

public class Contact
{
    public int ID { get; set; }

    public int ContactTypeId { get; set; }

    [ForeignKey("ContactTypeId")]
    public virtual ContactType ContactType { get; set; }

    [Required]
    public string Value { get; set; }

    [ForeignKey("PersonelId")]
    public virtual Personel Personel { get; set; }

    public int PersonelId { get; set; }
}

以下是每个联系人的类型信息。

public class ContactType
{
    public int ID { get; set; }
    [Required]
    public string Value { get; set; }
}

有人能让我朝着正确的方向前进吗?

3 个答案:

答案 0 :(得分:1)

您正在错误的地方进行加入。试试这个:

var model = (from person in personel
                where person.ID == id
                select new PersonelWithContactListDto {
                    PersonelName = person.PersonelName,
                    PersonelLastname = person.PersonelSurname,
                    PersonelPrivateNo = person.PersonelPrivateNo,
                    Contacts = (from contact
                                in person.Contacts
                                join contactType in contactTypes
                                on contact.ContactTypeId equals contactType.ID
                                select new ContactListDto {
                                    Value = contact.Value,
                                    ContactType = contactType.Value,
                                    ID = contact.ID
                                }).ToList()
                }).FirstOrDefault();

答案 1 :(得分:0)

显然你有一个id,而且你希望这个Personel只有id以及他所有Contacts。您不希望Personel的所有属性都包含此id,但只有PersonelNamePersonelLastnamePersonelPrivateNo

从提取的Contact的每个Personel中,您也不想要所有属性,但只有ValueContactTypeid < / p>

您的Personel类已经拥有一个包含您想要的Contacts的属性。那么为什么要加入呢?使用ICollection和你的框架(看起来像实体框架)将知道需要连接:

var personWithHisContacts = myDbContext.Personels
    .Where(person => person.Id == id)
    .Select(person => new
    {
        // select only the Person properties you plan to use:
        Name = person.PersonelName,
        LastName = person.PersonelLastName,
        PrivateNo = person.PersonelPrivateNo,

        // I want all contacts of this Person:
        Contacts = person.Contacts
            .Select(contact => new
            {
                // again: select only the properties you plan to use:
                Id = contact.Id,
                Value = contact.Value,
                ContactTypeValue = contact.ContactType.Value,
            })
            .ToList(),
    });

我认为使用ICollection的{​​{1}}是一种巧妙的方式,可以清楚地表明每个Contacts都有零个或多个Personel。它还隐藏在内部,这是使用两个带有外键的单独表来完成的。

您是否注意到Contacts部分占用了大部分查询?

您的框架将知道使用ICollection需要加入。如果您真的认为明确指定连接,请执行以下操作:

Select

var personWithHisContacts = myDbContext.Personels // from all Persons .Where(person => person.Id == id) // take the one with id .GroupJoin(myDbContext.Contacts // GroupJoin with all Contacts person => person.Id, // from each person take Id contact => contact.PersonelId, // from each contact take PersonelId (person, contacts) => new // when they match, make a new object { // containing only the properties you plan to use Name = person.PersonelName, LastName = person.PersonelLastName, PrivateNo = person.PersonelPrivateNo, // I want all contacts of this Person: Contacts = contacts.Select(contact => new { // again: select only the properties you plan to use: Id = contact.Id, Value = contact.Value, ContactTypeValue = contact.ContactType.Value, }) .ToList(), }); 部分并没有真正改变。 GroupJoin改变了ICollection的使用。我不明白为什么有人会更喜欢ICollection方法之上,但你真的想要......

答案 2 :(得分:-1)

看看这是否有帮助:

    class Program
    {
        static void Main(string[] args)
        {
            DB db = new DB();
            int id = 123;

            var model = (from personel in db.Personels
                         where personel.ID == id
                         from contact in db.ContactTypes

                         join contactType in db.ContactTypes on contact.ID equals contactType.ID

                         select new PersonelWithContactListDto
                         {
                             PersonelName = personel.PersonelName,
                             PersonelLastname = personel.PersonelSurname,
                             PersonelPrivateNo = personel.PersonelPrivateNo,
                             // here how to select my sublist. If I leverage
                             // let = dbobjects.DefaultIfEmpty() then I am no 
                             // longer able to specify contactType from another table.                             
                             Contacts = personel.Contacts.Select(x => new Contact() {
                                 Value = x.Value,
                                 ID = x.ID
                             }).ToList()
                         }).ToList();
        }
    }
    public class DB
    {
        public List<Personel> Personels { get; set; }
        public List<ContactType> ContactTypes { get; set; }
    }

    public class PersonelWithContactListDto
    {
        public string PersonelName { get; set; }

        public string PersonelLastname { get; set; }

        public int PersonelPrivateNo { get; set; }

        public List<Contact> Contacts { get; set; }
    }


    public class Personel
    {
        public int ID { get; set; }

        //[Required]
        public string PersonelName { get; set; }

        //[Required]
        public string PersonelSurname { get; set; }

        //[Required]
        //[Index(IsUnique = true)]
        public int PersonelPrivateNo { get; set; }

        public virtual ICollection<Contact> Contacts { get; set; }
    }

    public class Contact
    {
        public int ID { get; set; }

        public int ContactTypeId { get; set; }

        //[ForeignKey("ContactTypeId")]
        public ContactType ContactType { get; set; }

        //[Required]
        public string Value { get; set; }

        //[ForeignKey("PersonelId")]
        public virtual Personel Personel { get; set; }

        public int PersonelId { get; set; }
    }


    public class ContactType
    {
        public int ID { get; set; }
        //[Required]
        public string Value { get; set; }
    }