[英]Linq Projection to DTO for Nested/Hierarchical Collections
I have a User
and Product
entities which are defined as follows: 我有一个
User
和Product
实体,它们的定义如下:
public class User {
Guid Id { get; set; }
Guid ParentId { get; set; }
ICollection<Product> PermittedProducts { get; set; }
ICollection<User> Children { get; set; }
}
public class Product {
int Id { get; set; }
string Name { get; set; }
ICollection<User> PermittedUsers { get; set; }
}
Conceptually, a Product
has a collection of PermittedUsers
- ie users that can purchase the product. 从概念上讲,
Product
具有PermittedUsers
的集合-即可以购买产品的用户。 Additionally, each User
has a collection of PermittedProducts
, as well as a collection of child users, who also have their own collection of PermittedProducts
. 此外,每个
User
都有一个PermittedProducts
集合,还有一个子用户集合,这些子用户也有自己的PermittedProducts
集合。
I need to run a query via a repository to return a list of products. 我需要通过存储库运行查询以返回产品列表。 The repository method and DTO are defined as:
存储库方法和DTO定义为:
public ICollection<ProductListDto> GetProductsForUser(Guid userId) {
// Linq query here
}
public class ProductListDto {
int Id { get; set; }
string Name { get; set; }
ICollection<User> Users { get; set; }
}
The repository method needs to take a Guid userId
and retrieve the PermittedProducts
for that User AND the PermittedProducts
for the user's children. 该库方法需要采取一个GUID
userId
和检索PermittedProducts
为用户和 PermittedProducts
用户的孩子。
For example, if a product is available for a user and his two children, then the ProductListDto would have all three users in it's users collection. 例如,如果某个用户及其两个孩子都可以使用某个产品,则ProductListDto将在其用户集合中拥有所有三个用户。
As a further example, if a product is not available for a user, but it is available for his children, then this would need to be returned as well. 作为进一步的示例,如果产品对用户不可用,但是对他的孩子可用,则也需要将其退回。
Both the Product
and User
are available as aggregate roots, so I can use either a ProductRepository
or UserRepository
to query through, via EntityFramework's DbSet
. Product
和User
都可以作为聚合根使用,因此我可以通过EntityFramework的DbSet
使用ProductRepository
或UserRepository
进行查询。
At the moment my repository method is in the UserRepository
(but could move to the ProductRepository
if the query is simpler) and looks like: 目前,我的存储库方法位于
UserRepository
(但如果查询更简单,则可以移至ProductRepository
),如下所示:
public ICollection<ProductListDto> GetProductsForUser(Guid userId) {
// Linq query here - Set is the EF DbSet<User>
var products = from u in
Set.Where(x => x.Id == userId) //.... NOT SURE ABOUT THE REST!
}
My problem is I cannot work out how to write the Linq query to achieve what I need to do! 我的问题是我无法解决如何编写Linq查询来实现我需要做的事情!
EDIT 编辑
The answers so far don't address how to achieve the projection to the ProductListDto
到目前为止的答案还没有解决如何实现对
ProductListDto
的投影
How I would approach this is simply build a list of Id's from the parent UserId so this will contain the Parent UserId and all of it's ChildId's. 我将如何处理这只是从父UserId构建一个ID列表,因此它将包含父UserId及其所有ChildId。 From this list we can then select from Products where PermittedUsers contains one of these Id's.
然后,我们可以从此列表中选择其中PermittedUsers包含这些ID之一的产品。 This is where you can get the product list from.
您可以从这里获取产品列表。
var childIds = DbContext.Users.Where(x => x.Id == userId).SelectMany(y => y.Children.Select(z => z.Id)).ToList();
childIds.Add(userId);
var products = DbContext.Products.Where(x => x.Users.SelectMany(y => childIds.Contains(y.Id))).ToList();
Try this 尝试这个
userRepository.Where(u => u.Id == userId && u.ParentId == userId)
.SelectMany(u => u.PermittedProducts)
.GroupBy(p => p.Id)
.Select(u => u.First());
Line explanation - 1) Retrieves target user and his children - 2) Select all products from user collection we get in first line - 3- 4) Remove duplicates. 线路说明-1)检索目标用户及其孩子-2)从第一行获得的用户集中选择所有产品-3-4)删除重复项。
Note such linq can be translated into heavy sql query that can decrease performance. 请注意,此类linq可以转换为繁重的sql查询,这可能会降低性能。 Maybe it is better to call ToList after lines (1, 2 or 3).
也许最好在第(1、2或3)行之后调用ToList。 Also it is possible to write your own SQL query, store them in sql server and call them from code by name.
也可以编写自己的SQL查询,将其存储在sql服务器中,然后按名称从代码中调用它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.