网络核心:实体框架然后包含在Projection Select中

时间:2019-08-27 20:39:03

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

我正在尝试在实体框架中进行“包含选择”中的“然后包含”。

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

由于某些原因,在投影选择中,我不能仅选择Department中的列。 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

注意:由于Bridge表具有多对多关系,因此ProductType可以返回多个Department。

1 个答案:

答案 0 :(得分:0)

使用Include / ThenInclude不会更改Linq表达式的范围。因此,如果您要从ProductType生成查询,然后先从Include桥接表和Department表构建查询,则Select的表达式仍为ProductType,它将不会移至Department。

如果要查询具有特定产品类型的部门,并且该部门与桥接表之间存在多对多关系,则:

如果部门包含桥接实体的集合以获取其产品类型:

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子句简化为: / p>

.Where(d => d.ProductTypeDepartmentBridge.Any(b => 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
                }));

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

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

使用Select的优势在于,除非您选择整个实体并且希望将相关实体作为该返回的实体图的一部分包含在内,否则无需使用Include。从实体甚至相关实体中选择字段时,无需包括它们。