C# 通过导航属性连接的Lambda语法?

C# 通过导航属性连接的Lambda语法?,c#,linq,C#,Linq,我可以使用导航属性执行连接,这对我来说比较枯燥,因为我不会到处重复连接条件: (from c in db.Companies from e in c.Employees select new { Employee = e, Company = c}).ToList(); 因为ORM知道公司与员工的关系,所以使用c.Employees导航属性推断加入的FK标准 通过导航属性将multiple-from子句直接转换为extension/lambda语法是什么? 我知道有一个连接扩展方法,但要求您显

我可以使用导航属性执行连接,这对我来说比较枯燥,因为我不会到处重复连接条件:

(from c in db.Companies
from e in c.Employees
select new { Employee = e, Company = c}).ToList();
因为ORM知道公司与员工的关系,所以使用
c.Employees
导航属性推断加入的FK标准

通过导航属性将multiple-from子句直接转换为extension/lambda语法是什么?

我知道有一个连接扩展方法,但要求您显式地命名要比较的FK,而不是通过导航属性暗示条件。这是无效的,但希望能表达我的意图:

db.Companies
  .Join(c.Employees, /* don't want to explicitly name FKs*/)
  .Select(x => new { Employee = x.e, Company = x.c}).ToList();
当然,
Join(c.Employees
不起作用,因为在此上下文中没有
c
,但是想法是以某种方式使用companys.Employees导航属性来暗示加入标准

我知道我能做到:

db.Companies.Select(c => new { Employees = c.Employees, Company = c })
但这是一个不同的结果集,因为它会为每个公司返回一条记录,然后将员工列表作为嵌套属性。因此,每个相关组合都有一条记录,而不是第一条作为联接的记录,并且结果有一个
Employee
属性,而不是
employees
集合

我不确定,但是猜测
。SelectMany
是直接翻译。您不会得到对父对象的
c
引用,因此如果您执行以下操作中的多个操作:

db.Companies.SelectMany(c=>c.Employees).SelectMany(e=>e.VacationDays).Select(v => new { VacationDay = v, Employee = v.Employee, Company = v.Employee.Company })

在linq中,它要简单得多,因为在select的上下文中会有
c
e
v
。我不知道是否可以在扩展方法中表达相同的内容,以便所有三个别名/引用都被传递下来。也许只是这是扩展方法语法的结果,但希望有人能提供更好的等价物。

这不是很像:

db.Employees.Select(m => new { Employee = m, Company = m.Company });
既然每个员工都有一个公司,为什么不将导航属性“Company”添加到员工实体中呢

要获得假期,只需将其更改为以下内容:

 db.Employees.SelectMany(
 employee => employee.VacationDays, 
 (employee, vacationDay) => new 
  { 
      Employee = employee, 
      Company = employee.Company, 
      VacationDay = vacationDay 
  });
更新:

事实上,两者之间没有区别:

(from c in db.Companies
 from e in c.Employees
 select new { Employee = e, Company = c}).ToList();
以及:


SelectMany
确实是多个
from
子句映射到的内容

为了将变量保持在范围内,每个
SelectMany
需要将序列投影到一个新的匿名对象中,该对象将所有适当的变量保持在范围内:

var query = db.Companies.SelectMany(company => company.Employees, 
    (company, employee) => new
{
    company,
    employee
});
要为其他嵌套导航属性添加其他投影,只需重复该模式,然后调用
SelectMany

var query = db.Companies.SelectMany(company => company.Employees,
    (company, employee) => new
{
    company,
    employee
}).SelectMany(pair => pair.employee.VacationDays,
    (pair, vactionDay) => new
{
    pair.company,
    pair.employee,
    vactionDay,
});

有关此转换的更多详细信息和深入描述,以及它的扩展方式,请参阅。

他在
公司的
Employee
上有一个导航属性。这就是他所使用的。他试图使用它将查询投影到员工和公司的成对集合中。他使用query做得很好y语法,但无法使用方法语法。您没有在此答案中对该查询语法查询进行建模。这正是我的查询所做的。我指定了方法语法,只是不同的方法。EF将执行正确的联接,就像使用查询方式执行时一样。我没有注意到您将其反转,但是的,确实如此,尽管确实如此esn没有回答如何将给定的查询语法查询实际转换为方法语法的问题。谢谢,这将有助于其他对另一种方法感兴趣的人,但取决于关系的基数,在
Select
中对简单大小写以外的任何内容执行此类操作将变成cre中的练习积极性。并不是说Servy's总是更好,我只是想更好地理解我的LINQ表达式所代表的内容,看看直接翻译是否有吸引力。对我的答案补充了一点解释。目前唯一的问题是“哪种方式更快?”。如果您分析SQL查询结果并将其发布到某个地方,那将非常好。
var query = db.Companies.SelectMany(company => company.Employees,
    (company, employee) => new
{
    company,
    employee
}).SelectMany(pair => pair.employee.VacationDays,
    (pair, vactionDay) => new
{
    pair.company,
    pair.employee,
    vactionDay,
});