2016-08-03 127 views
1

我有以下查詢。不支持嵌套查詢。 Operation1 ='UnionAll'Operation2 ='MultiStreamNest'

var query = Repository.Query<Product>() 
    .Where(p => !p.IsDeleted && p.Article.ArticleSections.Count() > 0) 
    .Select(p => new 
    { 
     OfficeId = p.TariffCategory.Office.Id, 
     Office = p.TariffCategory.Office.Name, 
     Category = p.TariffCategory.Description, 
     ArticleId = p.Article.Id, 
     Article = p.Article.Title, 
     Destinations = p.ProductDestinations.OrderBy(pd => pd.Destination.Description).Select(pd => new { Id = pd.DestinationId, Name = pd.Destination.Description }), 
     GlobalDestinations = p.AllDestinationsInOffice, 
     p.Article.LastReviewedDate, 
     p.Article.CreatedDate, 
     p.Article.CreatedByEmployee 
    }); 
query = query.Concat(Repository.Query<Package>() 
    .Where(pkg => !pkg.IsDeleted && pkg.Article.ArticleSections.Count() > 0) 
    .Select(pkg => new 
    { 
     OfficeId = pkg.TariffCategory.Office.Id, 
     Office = pkg.TariffCategory.Office.Name, 
     Category = pkg.TariffCategory.Description, 
     ArticleId = pkg.Article.Id, 
     Article = pkg.Article.Title, 
     Destinations = pkg.PackageDestinations.OrderBy(pd => pd.Destination.Description).Select(pd => new { Id = pd.DestinationId, Name = pd.Destination.Description }), 
     GlobalDestinations = pkg.AllDestinationsInOffice, 
     pkg.Article.LastReviewedDate, 
     pkg.Article.CreatedDate, 
     pkg.Article.CreatedByEmployee 
    })); 
query = query.Concat(Repository.Query<Backgrounder>() 
    .Where(bkgd => !bkgd.IsDeleted && bkgd.Article.ArticleSections.Count() > 0) 
    .Select(bkgd => new 
    { 
     OfficeId = bkgd.TariffCategory.Office.Id, 
     Office = bkgd.TariffCategory.Office.Name, 
     Category = bkgd.TariffCategory.Description, 
     ArticleId = bkgd.Article.Id, 
     Article = bkgd.Article.Title, 
     Destinations = bkgd.BackgrounderDestinations.OrderBy(bd => bd.Destination.Description).Select(bd => new { Id = bd.DestinationId, Name = bd.Destination.Description }), 
     GlobalDestinations = bkgd.AllDestinationsInOffice, 
     bkgd.Article.LastReviewedDate, 
     bkgd.Article.CreatedDate, 
     bkgd.Article.CreatedByEmployee 
    })); 

// Apply filters 
if (OfficeIds.Any()) 
    query = query.Where(a => OfficeIds.Contains(a.OfficeId)); 
if (DestinationIds.Any()) 
    query = query.Where(a => a.GlobalDestinations || a.Destinations.Any(d => DestinationIds.Contains(d.Id))); 
if (!string.IsNullOrEmpty(ArticleTitle)) 
    query = query.Where(a => a.Article.Contains(ArticleTitle)); 
if (!string.IsNullOrEmpty(TariffCategory)) 
    query = query.Where(a => a.Category.Contains(TariffCategory)); 

// Sort results 
query = query.OrderBy(a=> a.Office).ThenBy(a => a.Category).ThenBy(a => a.Article); 

var articles = query.ToList(); 

但是,當我運行這個查詢時,我得到一個異常。

不支持嵌套查詢。 Operation1 ='UnionAll'Operation2 ='MultiStreamNest'

查詢搜索我的數據庫中的文章。由於文章可能與Product,PackageBackgrounder相關,並且我需要來自相關表格的信息,因此我會爲每個這些項目連接單獨的查詢。

我已將範圍縮小到Destinatons。顯然,這構成了與Concat()相關聯的查詢內的查詢。 (如果我刪除了第二個查詢和關聯的Concat()調用,它可以很好地工作。)

看了這一段時間後,我很難看到另一種方法來構建我的查詢,但沒有做太多,慢得多。

有沒有人看到我可能錯過了解決異常的任何技巧?

+0

遺憾的是沒有技巧可以使工作一包含投影內部集合成員的'Concat' /'Union'查詢,除了單獨執行它們並將結果合併到內存中。篩選器可以應用於每個查詢,但排序也應該在內存中。希望你沒有分頁。 –

+0

@IvanStoev:對。另一種選擇是將查詢基於我的'Article'表,但是從相關表中獲取信息(可能是三種類型之一)變得混亂。 (在這一點上沒有分頁。) –

+0

即使你從'文章'表開始,我不知道你如何到'目的地' –

回答

2

不幸的是沒有技巧。唯一合理的辦法,我看到,使這項工作沒有完全重寫它是單獨執行查詢(應用所有可能的過濾器),然後做Concat和排序在內存中是這樣的:

var queries = new [] 
{ 
    Repository.Query<Product>() 
    .Where(p => !p.IsDeleted && p.Article.ArticleSections.Count() > 0) 
    .Select(p => new 
    { 
     OfficeId = p.TariffCategory.Office.Id, 
     Office = p.TariffCategory.Office.Name, 
     Category = p.TariffCategory.Description, 
     ArticleId = p.Article.Id, 
     Article = p.Article.Title, 
     Destinations = p.ProductDestinations.OrderBy(pd => pd.Destination.Description).Select(pd => new { Id = pd.DestinationId, Name = pd.Destination.Description }), 
     GlobalDestinations = p.AllDestinationsInOffice, 
     p.Article.LastReviewedDate, 
     p.Article.CreatedDate, 
     p.Article.CreatedByEmployee 
    }), 

    Repository.Query<Package>() 
    .Where(pkg => !pkg.IsDeleted && pkg.Article.ArticleSections.Count() > 0) 
    .Select(pkg => new 
    { 
     OfficeId = pkg.TariffCategory.Office.Id, 
     Office = pkg.TariffCategory.Office.Name, 
     Category = pkg.TariffCategory.Description, 
     ArticleId = pkg.Article.Id, 
     Article = pkg.Article.Title, 
     Destinations = pkg.PackageDestinations.OrderBy(pd => pd.Destination.Description).Select(pd => new { Id = pd.DestinationId, Name = pd.Destination.Description }), 
     GlobalDestinations = pkg.AllDestinationsInOffice, 
     pkg.Article.LastReviewedDate, 
     pkg.Article.CreatedDate, 
     pkg.Article.CreatedByEmployee 
    }), 

    Repository.Query<Backgrounder>() 
    .Where(bkgd => !bkgd.IsDeleted && bkgd.Article.ArticleSections.Count() > 0) 
    .Select(bkgd => new 
    { 
     OfficeId = bkgd.TariffCategory.Office.Id, 
     Office = bkgd.TariffCategory.Office.Name, 
     Category = bkgd.TariffCategory.Description, 
     ArticleId = bkgd.Article.Id, 
     Article = bkgd.Article.Title, 
     Destinations = bkgd.BackgrounderDestinations.OrderBy(bd => bd.Destination.Description).Select(bd => new { Id = bd.DestinationId, Name = bd.Destination.Description }), 
     GlobalDestinations = bkgd.AllDestinationsInOffice, 
     bkgd.Article.LastReviewedDate, 
     bkgd.Article.CreatedDate, 
     bkgd.Article.CreatedByEmployee 
    }), 
}; 

// Apply filters 
if (OfficeIds.Any()) 
    for (int i = 0; i < queries.Length; i++) queries[i] = queries[i].Where(a => OfficeIds.Contains(a.OfficeId)); 
if (DestinationIds.Any()) 
    for (int i = 0; i < queries.Length; i++) queries[i] = queries[i].Where(a => a.GlobalDestinations || a.Destinations.Any(d => DestinationIds.Contains(d.Id))); 
if (!string.IsNullOrEmpty(ArticleTitle)) 
    for (int i = 0; i < queries.Length; i++) queries[i] = queries[i].Where(a => a.Article.Contains(ArticleTitle)); 
if (!string.IsNullOrEmpty(TariffCategory)) 
    for (int i = 0; i < queries.Length; i++) queries[i] = queries[i].Where(a => a.Category.Contains(TariffCategory)); 

// Switch to LINQ to Objects and concatenate the results 
var result = queries.Select(query => query.AsEnumerable()).Aggregate(Enumerable.Concat); 

// Sort results 
result = result.OrderBy(a=> a.Office).ThenBy(a => a.Category).ThenBy(a => a.Article); 

var articles = result.ToList(); 
+0

是的,謝謝。這是我最終採取的基本方法。 –