【问题标题】:Return data from related records with Linq to Entities使用 Linq 从相关记录返回数据到实体
【发布时间】:2013-09-13 01:22:52
【问题描述】:

我正在尝试使用实体框架从三个表中检索记录以填充 ListView。

这些表的示例结构是:

luPersonType

PersonTypeID
PersonTypeDescription

PersonID
FirstName
LastName
{...}
PersonTypeID

员工信息

EmployeeInfoID
PersonnelNumber
StartDate
{...}
PersonID

luPersonType 是一个查找表,其中包含用于区分人员类型的两个值(“Customer”和“Employee”)。luPersonType 与 People 具有 1:M 关系。

如果一个人是员工,他们将在 EmployeeInfo 表中存储有关他们的其他详细信息。人们与 EmployeeInfo 的关系是 1:1(理论上)。

示例数据:

luPersonType

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

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

员工信息

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

如您所见,John 和 Sue 都是员工,他们每个人在 EmployeeInfo 表中都有一条记录。

我想返回所有人员的列表,包括他们的 PersonType 描述和 EmployeeInfo 详细信息(如果有):

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

这将导致:

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

我首先尝试了这段代码,但它只返回了在 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();
}

由于这似乎会导致内部联接,因此我研究了编写此查询的不同方法。这是我的第二次尝试:

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
                }
}

这返回了所有四个记录,但它返回了 PersonnelNumber (System...String) 和 StartDate (System...DateTime) 的数据类型。

我已经阅读了 .Include 方法,但我也无法让它发挥作用。

第二个查询为我提供了我想要的所有记录,对我来说似乎更清晰,但我就是不知道如何从 EmployeeInfo 中检索实际数据值。

任何帮助将不胜感激!

【问题讨论】:

  • 你使用的是什么实体框架的方法?代码优先?数据库优先?模型优先?您是否定义了导航属性?
  • 数据库优先。英孚 5.0。我相信导航属性是在我第一次添加 .edmx 时定义的...?
  • 仅供参考,EmployeeId 实际上是 1:Many 而不是 1:1。即使是这样,也将是 1:0..1 而不是 1:1。问题是即使您只将此表用作 1:1,模型本身也支持 1:many(您可以在 EmployeeInfo 的两个不同行中输入相同的 PersonId),因此 EF 必须将其视为 1:many (即使您使用唯一约束,因为 EF 不支持约束)。
  • 为了创建 1:0 对 1 的关系,您应该使用相同的 FK & PK。所以在 EmployeeInfo 中 PersonID 应该是主键,根本不应该有 EmployeeInfoID 列。

标签: c# asp.net linq entity-framework linq-to-entities


【解决方案1】:

如果您的模型设置正确,您应该能够做到这一点(注意:未经测试,所以我不能 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
            };

这里的问题是 PersonnelInfo 实际上是 1:many,即使你只使用它作为 1:1,所以你必须选择第一条记录或如果没有关联则默认返回 null。

注意:这仅在使用 IQueryable 时有效,因为 EF 不会将空引用视为问题。如果将其转换为 IEnumerable,那么上面的代码将在 PersonnelNumber 和 StartDate 上抛出一个 execption,因为 b 对于某些记录将为空。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多