2016-03-01 2 views
0

У меня есть User и Product объектов, которые определены следующим образом:Linq проекция на DTO для вложенных/иерархических Коллекций

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 запрос для достижения того, что мне нужно сделать!

EDIT

Ответы до сих пор не решить, как добиться проекции на ProductListDto

+0

Hi Graham. Вы уверены, что хотите объединить эти две вещи таким образом? Вы сказали, что они являются совокупными корнями, которые для меня означают, что они являются отдельными проблемами? –

+0

К сожалению, так я должен это делать. Фактически он извлекает список продуктов на основе UserId (или список UserIds). – Graham

+0

Если вы действительно ** ** ** действительно хотите сделать это, это будет примерно так: context.Products.Include (p => p.PermittedUsers) .Where (p => p.PermittedUsers.Any (u => u.Id == userId)); Это должно предоставить вам список продуктов для пользователя. –

ответ

0

Попробуйте

userRepository.Where(u => u.Id == userId && u.ParentId == userId) 
      .SelectMany(u => u.PermittedProducts) 
      .GroupBy(p => p.Id) 
      .Select(u => u.First()); 

Line объяснение - 1) Извлекает цель пользователь и его дети - 2) Выделить все продукты из коллекции пользователя, которую мы получаем в первой строке ne - 3- 4) Удалить дубликаты.

Обратите внимание, что такой linq можно перевести на тяжелый sql-запрос, который может снизить производительность. Может быть, лучше позвонить ToList после строк (1, 2 или 3). Также можно написать собственный SQL-запрос, сохранить их в SQL-сервере и вызвать их из кода по имени.

1

Как бы я хотел это сделать, просто создайте список идентификаторов из родительского UserId, чтобы в нем содержался родительский идентификатор пользователя и все его дочерние элементы. Из этого списка мы можем выбрать из продуктов, в которых PermittedUsers содержит один из этих идентификаторов. Здесь вы можете получить список продуктов.

 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();