c# - 通过导航属性加入的 Lambda 语法?

标签 c# linq

我可以使用导航属性执行连接,这对我来说更枯燥,因为我没有在任何地方重复连接标准:

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

因为 ORM 知道 Companies 与 Employees 的关系,所以 c.Employees 导航属性用于推断加入的 FK 标准。

通过导航属性将 multiple from 子句的扩展/lambda 语法直接翻译成什么?

我知道有一个 Join 扩展方法,但需要您明确命名要比较的 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,但想法是以某种方式使用 Companies.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 中,它要简单得多,因为您将在选择的上下文中拥有 cev。我不知道您是否可以在扩展方法中表达相同的内容,以便所有三个别名/引用都被传递下来。也许只是扩展方法语法的结果,但希望有人能提供更好的等价物。

最佳答案

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,
});

参见 this blog post有关此转换及其扩展方式的更多详细信息和深入描述。

关于c# - 通过导航属性加入的 Lambda 语法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29421170/

相关文章:

c# - Linq 日期性能死亡

c# - Linq to SQL FirstOrDefault 不执行 SQL 查询

c# - WPF:日期时间选择器选择问题

c# - 使用内存映射 View 查看大位图图像

linq - 如何使用 LINQ 和连接检索 CRM Guid?

c# - 设计建议。使用 DataTable 或 List<MyObject> 作为通用规则检查器

c# - 两次调用 ReadAsFormDataAsync

c# - 创建自定义异常还是使用内置异常?

c# - 复制功能

linq - Linq的大于条件加盟