2016-08-03 125 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

是的,谢谢。这是我最终采取的基本方法。 –