2016-08-03 14 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(); 

ただし、このクエリを実行すると例外が発生します。

ネストされたクエリはサポートされていません。操作1 = 'UnionAll'操作2 = 'MultiStreamNest'

クエリは、データベース内の記事を検索します。記事はProductPackageまたはBackgrounderに関連する可能性があり、関連するテーブルの情報が必要なので、これらのアイテムごとに個別のクエリを連結します。

私はDestinatonsへの割り当てに絞っています。明らかに、これはConcat()に関連付けられたクエリ内のクエリを構成します。 (2番目の2つのクエリとそれに関連するConcat()コールを削除しても正常に動作します)

これはしばらくの間、私のクエリを大幅に遅くすることなく別の方法で構築することができません。

誰も私が例外を回避するために欠場したかもしれないトリックを見ていますか?

+0

残念ながらトリックが働いて作ることができません別々に実行し、結果をメモリにマージすることを除いて、コレクション内のコレクションメンバーを含む 'Concat' /' Union'クエリ。フィルタは各クエリに適用できますが、並べ替えはメモリ内にも存在する必要があります。あなたにページングがないことを願っています。 –

+0

@IvanStoev:そうです。もう1つの選択肢は、私の 'Article'テーブルに基づいてクエリを作成することですが、3つのタイプのうちの1つである可能性がある関連テーブルから情報を取得することは面倒です。 (この時点ではページングは​​ありません) –

+0

'Article'テーブルから始めても、' Destinations'にどうやって到達するのか分かりません。 –

答えて

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

ええ、ありがとう。これが私が取り上げる基本的なアプローチです。 –

関連する問題