【问题标题】:Net Core: Entity Framework ThenInclude with Projection SelectNet Core:Entity Framework ThenInclude 和 Projection Select
【发布时间】:2019-08-27 20:39:03
【问题描述】:

我正在尝试在实体框架中使用 Select Projection 执行 ThenInclude。

我们有三个表,ProductType 连接到 ProductTypeDepartmentBridge,然后连接到 Departments 表。

由于某种原因,在投影选择中,我不能只选择部门中的列。 Intellisense 给出一个错误,它不会出现。但是,我至少可以看到然后包括到 Department 表。

        var departmentsByProductType = unitOfWork.DBSet<Productype>()
            .Include(d => ProductTypeDepartmentBridge)
            .ThenInclude(d => d.Department)
            .Where(d => d.ProductTypeId == 5)
            .Select(d => new 
            {
                DepartmentId = d.DepartmentId,
                DepartmentName = d.DepartmentName
            });

错误:

                DepartmentId = d.DepartmentId,
                DepartmentName = d.DepartmentName

注意:一个 ProductType 可以返回多个部门,因为 Bridge 表具有多对多关系。

【问题讨论】:

  • 我认为您的意思是改用.Select()。将.Include() 与投影一起使用没有任何意义。
  • 您遇到了什么具体错误?

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


【解决方案1】:

使用 Include/ThenInclude 不会更改 Linq 表达式的范围。因此,如果您从 ProductType 和 Include 桥接表和 Department 表构建查询,Select 的表达式仍然是 ProductType,它不会移动到 Department。

如果您要查询具有特定 ProductType 并且与桥接表是多对多关系的部门,则:

如果部门包含一组桥接实体以获取其产品类型:

var departmentsByProductType = unitOfWork.DbSet<Department>()
    .Where(d => d.ProductTypeDepartmentBridge.Any(b => b.ProductType.ProductTypeId == 5))
    .Select(d => new 
    {
        DepartmentId = d.DepartmentId,
        DepartmentName = d.DepartmentName
    });

如果桥接表将其 PK 映射为 ProductTypeId+DepartmentId 的复合键,或者将 FK 映射到实体中,则可以稍微简化一下...您可以将 Where 子句简化为:

.Where(d =&gt; d.ProductTypeDepartmentBridge.Any(b =&gt; b.ProductTypeId == 5))

如果您没有从部门返回桥梁的链接:

// This should work....
var departmentsByProductType = unitOfWork.DBSet<Productype>()
            .Where(p => p.ProductTypeId == 5)
            .SelectMany(p => p.ProductTypeDepartmentBridge.Department
                .Select( d => new 
                {
                    DepartmentId = d.DepartmentId,
                    DepartmentName = d.DepartmentName
                }));
// but if not, this will work...
var departmentsByProductType = unitOfWork.DBSet<Productype>()
            .Where(p => p.ProductTypeId == 5)
            .SelectMany(p => p.ProductTypeDepartmentBridge
                .Select( b => new 
                {
                    DepartmentId = b.Department.DepartmentId,
                    DepartmentName = b.Department.DepartmentName
                }));

在第一个示例中,我们通过使用Any 检查桥接表,遍历部门并仅获取具有所需产品类型链接的部门。返回的唯一部门是包含该产品类型链接的部门。

在第二个示例中,我们转到产品类型,然后使用SelectMany 表示我们要从集合中获取多个结果。这将通过桥接实体为每个相关部门提供一行。从那里我们使用Select获取部门详细信息。有两种风格,因为我不能 100% 确定您可以直接通过 SelectMany 到达部门,您可能需要在桥接实体上使用 SelectMany,然后在 .Department 上使用 Select 来获取部门。我包括两个变种以防万一。尝试第一个,如果不起作用,请使用第二个。

使用Select 的优点是您不需要使用Include,除非您选择整个实体并希望将相关实体作为返回的实体图的一部分。从实体甚至相关实体中选择字段时,您不需要包含它们。

【讨论】:

猜你喜欢
  • 2021-11-29
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多