2016-03-01 81 views
0

我有限定有UserProduct實體如下:的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; } 
} 

從概念上講,ProductPermittedUsers的集合 - 即可以購買該產品的用戶。另外,每個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和檢索該用戶PermittedProductsPermittedProducts用戶的孩子。

例如,如果產品適用於用戶及其兩個子女,則ProductListDto將擁有其用戶集合中的所有三個用戶。作爲進一步的例子,如果產品對於用戶不可用,但是它可用於他的孩子,那麼這也需要被返回。

無論是ProductUser可作爲總根,所以我可以使用一個ProductRepositoryUserRepository查詢通過,通過的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

+0

嗨格雷厄姆。你確定你想以這種方式將這兩樣東西結合在一起嗎?你說他們都是聚合根源,對我來說這意味着他們是單獨的擔憂? –

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

行解釋 - 1)獲取目標用戶和他的孩子 - 2)選擇我們在第一次獲得的用戶集合中的所有產品ne - 3- 4)刪除重複項。

請注意,這樣的linq可以轉換爲可以降低性能的繁重sql查詢。也許最好在行(1,2或3)之後調用ToList。也可以編寫自己的SQL查詢,將它們存儲在sql server中並通過名稱從代碼中調用它們。

1

我將如何處理這個問題,只需從父UserId構建一個Id列表,以便它包含父UserId及其所有ChildId。從這個列表中,我們可以從產品中進行選擇,其中PermittedUsers包含這些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();