如何分配给 LinqToEntities C# 中的 List<string>

How to assign to a List<string> in LinqToEntities C#

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

        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 的自定义 setter,但这仍然会为查询 returns 的每个所有者进行另一次数据库往返。

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

编辑和回答(因为罗伯特·麦基在他的评论中引导我找到答案)。

答案是像这样使用 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 语句,因此不会抛出异常。

每天学点新东西。

设置您的导航属性,然后您的查询将变为:

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 方法。