嵌套/分层集合的 DTO Linq 投影
本文关键字:DTO Linq 投影 集合 分层 嵌套 | 更新日期: 2023-09-27 18:36:48
我有一个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; }
}
从概念上讲,Product
具有一组PermittedUsers
- 即可以购买该产品的用户。此外,每个User
都有一个 PermittedProducts
的集合,以及一个子用户的集合,这些用户也有自己的PermittedProducts
集合。
我需要通过存储库运行查询以返回产品列表。 存储库方法和 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; }
}
存储库方法需要获取 Guid userId
并检索该用户的PermittedProducts
和用户子项的PermittedProducts
。
例如,如果产品可供用户及其两个子级使用,则 ProductListDto 将在其用户集合中具有所有三个用户。
再举一个例子,如果产品对用户不可用,但对他的子项可用,那么也需要返回。
Product
和User
都可以作为聚合根使用,因此我可以使用ProductRepository
或UserRepository
通过EntityFramework的DbSet
进行查询。
目前我的存储库方法在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!
}
我的问题是我无法弄清楚如何编写 Linq 查询来实现我需要做的事情!
编辑
到目前为止,答案还没有解决如何实现对ProductListDto
的投影
我的方法就是简单地从父用户 ID 构建一个 Id 列表,这样它将包含父用户 ID 及其所有 ChildId。然后,我们可以从允许用户包含这些 ID 之一的产品中进行选择。这是您可以从中获取产品列表的地方。
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();
试试这个
userRepository.Where(u => u.Id == userId && u.ParentId == userId)
.SelectMany(u => u.PermittedProducts)
.GroupBy(p => p.Id)
.Select(u => u.First());
线路解释 - 1)检索目标用户及其子用户 - 2)从用户集合中选择我们在第一行获得的所有产品 - 3- 4) 删除重复项。
请注意,此类 linq 可以转换为繁重的 sql 查询,这会降低性能。也许最好在行(1、2 或 3)之后调用 ToList。也可以编写自己的SQL查询,将它们存储在sql服务器中,然后按名称从代码调用它们。