【问题标题】:How to assign to a List<string> in LinqToEntities C#如何在 LinqToEntities C# 中分配给 List<string>
【发布时间】:2015-12-17 17:35:38
【问题描述】:

希望我只是遗漏了一些明显的东西,但这是我的查询

        var data = (from project in _db.Projects 
                    where project.Id == id
                    let primaryCategory = (from c in _db.Categories
                                           where c.CategoryID == project.PrimaryCategory
                                           select c.Name)
                    let categories = (from c in _db.ProjectCategories
                                      join pc in _db.Projects_ProjectCategories on c.ProjectCategoryID equals pc.ProjectCategoryID
                                      where pc.ProjectID == project.ProjectID
                                      select c.Name)
                    let owner = (from o in _db.Owners
                                 join po in _db.App_Projects_Owners on o.OwnerID equals po.OwnerID
                                               where po.ProjectID == project.ProjectID
                                               select new OwnerModel
                                               {
                                                   Owner = o,
                                                   Project = project,
                                                   PrimaryCategory = primaryCategory.FirstOrDefault(),
                                                   Categories = categories.ToList()
                                               })

                    select new
                    {
                        owner,
                        project
                    }).FirstOrDefault();

其中 OwnerModel.Categories 是一个字符串列表。我不能在查询中使用 ToList(),因为它给出了一个具体化错误。我添加了一个使用 IQueryable 的自定义设置器,但是对于查询返回的每个所有者,这仍然会再次往返于数据库。

那么您应该如何在子查询中分配基本列表?

编辑和回答(因为 Robert McKee 在他的评论中引导我找到答案)。

答案就是像这样使用group by子句

var data = (from project in _db.Projects 
            where project.Id == id
            let primaryCategory = (from c in _db.Categories
                                           where c.CategoryID == project.PrimaryCategory
                                           select c.Name)
                    let categories = (from c in _db.ProjectCategories
                                      join pc in _db.Projects_ProjectCategories on c.ProjectCategoryID equals pc.ProjectCategoryID
                                      where pc.ProjectID == project.ProjectID
                                      group c.Name by pc.ProjectCategoryID into x
                                      select x.ToList())
                    let owner = (from o in _db.Owners
                                 join po in _db.App_Projects_Owners on o.OwnerID equals po.OwnerID
                                               where po.ProjectID == project.ProjectID
                                               select new OwnerModel
                                               {
                                                   Owner = o,
                                                   Project = project,
                                                   PrimaryCategory = primaryCategory.FirstOrDefault(),
                                                   Categories = categories
                                               })
                    select new
                    {
                        owner,
                        project
                    }).FirstOrDefault();

特别注意涉及的位

group c.Name by pc.ProjectCategoryID into x 
select x.ToList()

在您深入了解到底发生了什么之前,它的工作原理似乎违反直觉。我在上面使用 categories.ToList() 调用的方法试图使用 System.Collection.Generics ToList 函数,并且该列表没有任何方法将表达式转换为 sql。但是,通过使用 group by 子句,我创建了一个专门的 Enumerable IGrouping 并在其上调用 ToList 函数。该函数可以翻译成sql语句,因此不会抛出异常。

每天学习新东西。

【问题讨论】:

  • 如果你设置了导航属性,这会干净很多。

标签: c# sql-server linq-to-entities


【解决方案1】:

设置你的导航属性,然后你的查询变成这样:

var data=db.Projects
  .Include(p=>p.PrimaryCategory)
  .Include(p=>p.Categories)
  .Include(p=>p.Owner) // or .Include(p=>p.Owners) if projects can have multiple owners
  .First(p=>p.Id == id);

至于子对象,您正在寻找group by 子句或.GroupBy 方法。

【讨论】:

  • 这是一个很好的解决方法,我已经设置了导航属性,但是我在生产中使用的查询是使用这些让我们抓取 4 个不同的数据块(基本上不会有要导航的路线)。但是我仍然想知道您将如何处理分配给子查询中的列表。
  • 我可能对您的要求感到困惑,部分原因是我认为您使用了错误的术语。子查询是查询中的查询,与返回内容的结构无关。如果您正在谈论一个有很多孩子的对象,那么这就像一个组/组,您可以在其中调用 .ToList。
  • Group by 是正确的答案。谢谢罗伯!我知道这很简单,我只是想念它。如果您发布它,我会将其标记为正确答案。
猜你喜欢
  • 2015-10-12
  • 2012-06-21
  • 2020-11-04
  • 2016-04-18
  • 2017-09-24
  • 2020-08-26
  • 1970-01-01
  • 1970-01-01
  • 2012-07-21
相关资源
最近更新 更多