.SelectMany()并从多个相关表中获取数据

时间:2011-01-31 23:00:28

标签: linq entity-framework entity-framework-4

此查询返回员工ID,姓名,公司ID,公司名称和公司城市。我缺少员工电子邮件地址(存储在EmployeeEmailAddress表中的emailAddress)和员工电话号码(存储在EmployeePhoneNumbers表中的phoneNumber)。

我需要添加.SelectMany()以获取母公司关系并访问公司ID,名称和城市。但是,现在我无法访问PersonOrgMap表中找不到的任何属性。我无法导航到任何其他表。删除.SelectMany()允许我导航到其他表但我无法访问父公司信息。

var employees = Contacts.Where(c => c.ContactAttributes
.Any (ca => ca.AttributeID == 1153))
.SelectMany (x => x.ChildPersonOrgMaps)
.Select (c => new { employeeId = c.Child.ContactID,
          c.Child.FirstName,
          c.Child.LastName,
          companyId = c.ParentContactID,
          c.Parent.OrganizationName,
          c.Parent.City
        }
         )
.OrderBy (c =>c.LastName ).ThenBy(x => x.FirstName)
.Dump();

4 个答案:

答案 0 :(得分:16)

如果你热衷于方法语法,那么SelectMany()上有一个重载,它也让你可以访问“source”和“result”对象:

.SelectMany(x => x.ChildPersonOrgMaps, (x, c) => new { x, c })
.Select(xc => new 
{ 
    xc.x.Attribute1,
    xc.x.Attribute2,
    xc.c.Child.Attribute3,
    xc.c.Attribute4
});

答案 1 :(得分:5)

这是查询表达式真正有用的地方。如果你这样开始查询:

from c in Contacts
where c.ContactAttributes.Any (ca => ca.AttributeID == 1153))
from om in c.ChildPersonOrgMaps
...

您稍后可以在查询中访问 c om 变量。 C#通过选择“携带”原始变量的临时匿名类型将其转换为SelectMany调用。查看此问题的最佳方法是在LINQPad中将查询编写为查询表达式,然后查看lambda选项卡以查看转换为流利语法。

答案 2 :(得分:0)

我同意Joe Albahari - 使用查询语法。这是(我所知道的)你可以使用方法语法无法进行查询的一件事。

您可以尝试选择包含父对象和子对象的匿名类型,但我不认为EF会非常喜欢它。

var employees = Contacts.Where(c => c.ContactAttributes 
.Any (ca => ca.AttributeID == 1153)) 
.SelectMany (x => new { Parent = x, Child = x.ChildPersonOrgMaps })
// etc

答案 3 :(得分:0)

我正在学习LINQ,我更喜欢拆分命令,这样我就可以知道发生了什么。作为接受的答案,它肯定没有效率,但可能会被正在学习LINQ的任何人使用。

我宁愿用一些虚拟数据进行演示

var persons = new [] {"John's", "Mike's", "Albert's"};
var objects = new [] {"car", "house", "bicycle"};
var colors  = new [] {"red", "blue", "green", "yellow"};


var firstPair = persons.SelectMany(_ => objects, (p, o) => new {
   Person = p,
   Object = o
});

var secondPair = firstPair.SelectMany(_ => colors, (fp, c) => new {
   Person = fp.Person,
   Object = fp.Object,
   Color = c
});

它在LINQ Pad中提供这样的输出。 enter image description here