首页 > 解决方案 > C# LINQ,带有 JOIN 和 GroupBy 的脚本抛出异常

问题描述

我正在使用 .NET CORE 5 平台上的 LINQ 脚本以及 Entity Framework Core 5.0.8 脚本简单地与组一起左加入但出现异常,如果不应用组,那么我可以看到结果......不是确定我在拼图中缺少什么

例外

could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'

代码

var a1 =
  (from site in db.Sites
  join machine in db.Machines on site.SiteId equals machine.SiteId into sm
  from siteMachines in sm.DefaultIfEmpty()
  where site.SiteId == SiteId
  group siteMachines by site into groupedSiteMachines
  select new
      {
       listedSite = groupedSiteMachines.Key,
       SiteMachines = groupedSiteMachines.FirstOrDefault() == null? null : groupedSiteMachines
      }
  ).ToList() ;

标签: c#linqentity-framework-core.net-5

解决方案


因此,您有SitesMachines,并且站点和机器之间存在一对多的关系:每个站点上都有零个或多个机器,并且每个机器都在一个站点上,即外键 SiteId 所指的站点。

在我看来,您有一个值 siteId,并且您希望该站点具有该值作为主键和该站点上的所有机器。

每当您具有一对多关系时,例如具有零个或多个学生的学校,具有零个或多个订单的客户,或者在您的情况下,具有其机器的站点,请考虑使用Queryable.GroupJoin的重载之一

int siteId = 42;

var siteWithItsMachines = dbContext.Sites

    // keep only the site with siteId
    .Where(site => site.Id == siteId)

    // To get the Machines on each Site, do a GroupJoin:
    .GroupJoin(dbContext.Machines,

    site => site.Id              // from each Site take the primary key
    machine => machine.SiteId,   // from each Machine take the foreign key

    // parameter resultSelector: from every Site with all Machines on this Site
    // make one new object:
    (site, machinesOnThisSite) => new
    {
        // Select the Site properties that you plan to use:
        Id = site.Id,
        Name = site.Name,
        Location = site.Location,
        ...

        Machines = machinesOnThisSite.Select(machine => new
        {
            // select the Machine properties that you plan to use:
            Id = machine.Id,
            Type = machine.Type,
            ...

            // not needed, you already got the value
            // SiteId = machine.SiteId,
        })
        .ToList(),
    });

为了提高效率,我不选择完整的站点或完整的机器,而只选择我计划使用的属性。


推荐阅读