C# LINQ,带有 JOIN 和 GroupBy 的脚本抛出异常
C# LINQ, script with JOIN and GroupBy throwing exception
我正在处理 .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() ;
您无法在 LINQ to Entities 中获取分组项目的第一个元素。考虑按以下方式重写查询:
var query =
from site in db.Sites
where site.SiteId == SiteId
from siteMachines in db.Machines.Where(machine => site.SiteId == machine.SiteId)
.Take(1)
.DefaultIfEmpty()
select new
{
listedSite = site,
SiteMachines = siteMachines
};
在 .NET 5 中,GroupBy
未转换为 SQL
查询,您应该使用 AsEnumerable
或 .ToList
在 GroupBy
语句之前。
首先你应该从 SQL
中读取数据而不需要任何 GroupBy
语句,当数据接收到你的内存中时,使用 GroupBy
.
所以你有 Sites
和 Machines
,并且站点和机器之间存在一对多关系:每个站点上都有零个或多个机器,并且每个机器都打开正好一个Site,即外键SiteId所指的Site。
在我看来,您有一个值 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(),
});
为了提高效率,我没有 select 完整的站点和完整的机器,而是我打算使用的属性。
我正在处理 .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() ;
您无法在 LINQ to Entities 中获取分组项目的第一个元素。考虑按以下方式重写查询:
var query =
from site in db.Sites
where site.SiteId == SiteId
from siteMachines in db.Machines.Where(machine => site.SiteId == machine.SiteId)
.Take(1)
.DefaultIfEmpty()
select new
{
listedSite = site,
SiteMachines = siteMachines
};
在 .NET 5 中,GroupBy
未转换为 SQL
查询,您应该使用 AsEnumerable
或 .ToList
在 GroupBy
语句之前。
首先你应该从 SQL
中读取数据而不需要任何 GroupBy
语句,当数据接收到你的内存中时,使用 GroupBy
.
所以你有 Sites
和 Machines
,并且站点和机器之间存在一对多关系:每个站点上都有零个或多个机器,并且每个机器都打开正好一个Site,即外键SiteId所指的Site。
在我看来,您有一个值 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(),
});
为了提高效率,我没有 select 完整的站点和完整的机器,而是我打算使用的属性。