简体   繁体   English

使用Linq将数据从相关记录返回到实体

[英]Return data from related records with Linq to Entities

I am trying to retrieve records to populate a ListView, using Entity Framework, from three tables. 我正在尝试从三个表中检索记录以使用Entity Framework填充ListView。

An example structure of these tables is: 这些表的示例结构为:

luPersonType luPersonType

PersonTypeID
PersonTypeDescription

People

PersonID
FirstName
LastName
{...}
PersonTypeID

EmployeeInfo EmployeeInfo

EmployeeInfoID
PersonnelNumber
StartDate
{...}
PersonID

luPersonType is a lookup table which holds two values ("Customer" and "Employee) used to differentiate types of people. luPersonType has a 1:M relationship to People. luPersonType是一个查找表,其中包含用于区分人员类型的两个值(“ Customer”和“ Employee”)luPersonType与People的关系为1:M。

If a person is an Employee, they will have additional details stored about them in the EmployeeInfo table. 如果某人是Employee,那么他们将在EmployeeInfo表中存储有关他们的其他详细信息。 People has a 1:1 (theoretical) relationship to EmployeeInfo. 人们与EmployeeInfo具有1:1(理论上)的关系。

Example data: 示例数据:

luPersonType luPersonType

PersonTypeID----PersonTypeDescription
1---------------Customer
2---------------Employee

People

PersonID----FirstName---LastName---PersonTypeID
1-----------Jane--------Doe--------1
2-----------John--------Doe--------2
3-----------Bob---------Smith------1
4-----------Sue---------Jones------2

EmployeeInfo EmployeeInfo

EmployeeInfoID----PersonnelNumber----StartDate----PersonID
1-----------------ABC123-------------1/1/13-------2
2-----------------XYZ456-------------2/1/13-------4

As you can see, both John and Sue are Employees and they each have a record in the EmployeeInfo table. 如您所见,John和Sue都是雇员,并且他们各自在EmployeeInfo表中都有一条记录。

I would like to return a list of all people, with their PersonType description, and EmployeeInfo details (if any): 我想返回所有人的列表,其中包括其PersonType描述和EmployeeInfo详细信息(如果有):

luPersonType.PersonTypeDescription,
People.LastName + ", " + People.FirstName AS FullName,
EmployeeInfo.PersonnelNumber,
EmployeeInfo.StartDate

This would result in: 这将导致:

PersonTypeDescription----FullName----PersonnelNumber----StartDate
Customer-----------------Doe, Jane---NULL---------------NULL
Employee-----------------Doe, John---ABC123-------------1/1/13
Customer-----------------Smith, Bob--NULL---------------NULL
Employee-----------------Jones, Sue--XYZ456-------------2/1/13

I first tried this code, but it only returned People that had records in both People and EmployeeInfo (inner join?): 我首先尝试了这段代码,但是它只返回在People和EmployeeInfo中都具有记录的People(内部联接?):

using(MyEntities ctx = new MyEntities())
{
    var query = from a in ctx.People
                join b in ctx.luPersonType on a.PersonTypeID equals b.PersonTypeID
                join c in ctx.EmployeeInfo on a.PersonID equals c.PersonID
                orderby a.LastName
                select new
                {
                    b.PersonTypeDescription,
                    FullName = a.LastName + ", " + a.FirstName,
                    c.PersonnelNumber,
                    c.StartDate
                };

    RadListViewPeople.DataSource = query.ToList();
}

Since that seemed to result in an inner join, I looked into different ways to write this query. 由于这似乎导致内部联接,因此我研究了编写此查询的不同方法。 Here is my second try: 这是我的第二次尝试:

using (MyEntities ctx = new MyEntities())
{
    var query = from a in ctx.People
                orderby a.LastName
                select new
                {
                    a.luPersonType.PersonTypeDescription,
                    FullName = a.LastName + ", " + a.FirstName,
                    PersonnelNumber = from b in a.EmployeeInfos
                                      select b.PersonnelInfo
                    StartDate = from b in a.EmployeeInfos
                                select b.StartDate
                }
}

This returned all four records, but it returned the datatype for PersonnelNumber (System...String) and StartDate (System...DateTime). 这将返回所有四个记录,但返回的是PersonnelNumber(System ... String)和StartDate(System ... DateTime)的数据类型。

I have read about the .Include method, but I haven't been able to get that to work, either. 我已经阅读了有关.include方法的信息,但我也无法使其正常工作。

The second query gave me all the records that I wanted and it seems cleaner to me, but I just can't figure out how to retrieve the actual data values from EmployeeInfo. 第二个查询提供了我想要的所有记录,对我来说似乎更干净,但是我无法弄清楚如何从EmployeeInfo中检索实际数据值。

Any help will be greatly appreciated! 任何帮助将不胜感激!

If your model is setup properly, you should simply be able to do this (note: not tested, so i'm not 100% sure the syntax is correct, but it should give you what you need to solve the problem, i'm also guessing at the name of the navigation property EmployeeInfo): 如果您的模型设置正确,那么您应该能够做到这一点(注意:未经测试,因此我不是100%确定语法正确,但是它可以为您提供解决问题的所需条件,我还猜测导航属性EmployeeInfo的名称):

var query = from a in ctx.People
            let b = a.EmployeeInfo.FirstOrDefault()
            orderby a.LastName
            select new {
                a.luPersonType.PersonTypeDescription,
                FullName = a.LastName + ", " + a.FirstName,
                b.PersonnelNumber,
                b.StartDate
            };

The problem here is the PersonnelInfo is actually 1:many, even though you only use it as a 1:1, so you have to select the first record or Default to return null if no association. 这里的问题是PersonnelInfo实际上是1:many,即使您仅将其用作1:1,所以如果没有关联,则必须选择第一个记录或Default以返回null。

Note: this only works when using IQueryable, because EF does not treat null references as problems. 注意:这仅在使用IQueryable时有效,因为EF不会将空引用视为问题。 If this were converted to an IEnumerable, then the code above would throw an execption on PersonnelNumber and StartDate because b would be null for some records. 如果将其转换为IEnumerable,则上面的代码将对PersonnelNumber和StartDate引发执行,因为对于某些记录,b将为null。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM