I am trying to conduct ThenInclude with Select Projection in Entity Framework.
We have three tables, ProductType joins to ProductTypeDepartmentBridge, which then joins t
Using Include/ThenInclude does not change the scope of the Linq Expression. So if you are building a query from ProductType and Include
the bridging table and then the Department table, the expression for the Select
remains ProductType, it doesn't move to Department.
If you want to query Departments that have a particular ProductType and it is a many-to-many relationship with the bridging table then:
If Departments contain a collection of the bridging entities to get to their product type:
var departmentsByProductType = unitOfWork.DbSet<Department>()
.Where(d => d.ProductTypeDepartmentBridge.Any(b => b.ProductType.ProductTypeId == 5))
.Select(d => new
{
DepartmentId = d.DepartmentId,
DepartmentName = d.DepartmentName
});
This can be simplified slightly if the bridging table either maps it's PK as a composite key of both ProductTypeId+DepartmentId or otherwise has the FKs mapped in the entity... You can simplify the Where
clause to:
.Where(d => d.ProductTypeDepartmentBridge.Any(b => b.ProductTypeId == 5))
If you don't have the link from department back to the bridge:
// 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
}));
In the first example we iterate over Departments and take only the ones that have a link to the desired product type by leveraging an Any
check through the bridging table. The only departments returned are ones that contain a link to that product type.
In the second example we go to the Product Type, but then use SelectMany
to say we want to grab multiple results from a collection. This will give us a row for each related Department via the bridging entity. From there we use Select
to get the department details. There are 2 flavours since I'm not 100% sure you can get to the Department via the SelectMany
directly, you might need to SelectMany
on the bridging entity, then Select
on the .Department to get the departments. I included both variants in case. Try the first one, then use the 2nd if it doesn't work.
The advantage of using Select
is that you don't need to use Include
unless you are selecting whole entities and want to include related entities as part of that returned entity graph. When selecting fields from an entity, or even related entities, you don't need to include them.