GroupBy 表达式翻译失败
GroupBy Expression failed to translate
//Model
public class Application
{
[Key]
public int ApplicationId { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime ConfirmedDate { get; set; }
public DateTime IssuedDate { get; set; }
public int? AddedByUserId { get; set; }
public virtual User AddedByUser { get; set; }
public int? UpdatedByUserId { get; set; }
public virtual User UpdatedByuser { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string TRN { get; set; }
public string EmailAddress { get; set; }
public string Address { get; set; }
public int ParishId { get; set; }
public Parish Parish { get; set; }
public int? BranchIssuedId { get; set; }
public BranchLocation BranchIssued { get; set; }
public int? BranchReceivedId { get; set; }
public BranchLocation BranchReceived {get; set; }
}
public async Task<List<Application>> GetApplicationsByNameAsync(string name)
{
if (string.IsNullOrEmpty(name))
return null;
return await _context.Application
.AsNoTracking()
.Include(app => app.BranchIssued)
.Include(app => app.BranchReceived)
.Include(app => app.Parish)
.Where(app => app.LastName.ToLower().Contains(name.ToLower()) || app.FirstName.ToLower()
.Contains(name.ToLower()))
.GroupBy(app => new { app.TRN, app })
.Select(x => x.Key.app)
.ToListAsync()
.ConfigureAwait(false);
}
上面的 GroupBy
表达式无法在 VS Studio 中编译。我的 objective 是 运行 按包含用户给定字符串的名称过滤结果的查询,然后它应该按类似的 TRN
数字对结果进行分组 returning 这些应用程序的列表到 return 查看。我想我真的很接近,但似乎无法弄清楚查询的最后一点。任何指导表示赞赏。
显示错误
InvalidOperationException: The LINQ expression 'DbSet<Application>
.Where(a => a.LastName.ToLower().Contains(__ToLower_0) || a.FirstName.ToLower().Contains(__ToLower_0))
.GroupBy(
source: a => new {
TRN = a.TRN,
app = a
},
keySelector: a => a)' 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 either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()
更新
似乎这肯定是由于自最近更新以来 .net 核心 3.x 和 EF 核心一起玩的方式发生了变化。我不得不使用 AsEnumerable()
而不是 ToListAsync()
将其更改为客户评估。 Steve py 给出的其余查询使用此方法。即使在阅读了文档之后我也不知道 groupby 在 LINQ 中是如何工作的,所以这对我帮助很大。然而,将查询带到客户端 eval 可能会出现性能问题。
基于此:
I want to group by TRN which is a repeating set of numbers eg.12345, in the Application table there may be many records with that same sequence and I only want the very latest row within each set of TRN sequences.
我相信这应该能满足您的需求:
return await _context.Application
.AsNoTracking()
.Include(app => app.BranchIssued)
.Include(app => app.BranchReceived)
.Include(app => app.Parish)
.Where(app => app.LastName.ToLower().Contains(name.ToLower()) || app.FirstName.ToLower()
.Contains(name.ToLower()))
.GroupBy(app => app.TRN)
.Select(x => x.OrderByDescending(y => y.CreatedAt).First())
.ToListAsync()
.ConfigureAwait(false);
GroupBy
表达式应该表示您要分组的依据。在您的情况下,TRN。从那里开始,当我们执行 select 时,x
表示每个 "group",其中包含属于每个 TRN 的 Enumarable 应用程序集。因此,我们使用 First
.
按 CreatedAt 日期降序排列到 select 最新的那些
试一试。如果这不是您想要的,请考虑为您的问题添加一个示例集以及所需的输出与此处产生的输出/错误。
我遇到过类似的问题,我觉得它既有趣又愚蠢。似乎 EF 团队禁止在 GROUP BY 之前执行 WHERE,因此它不起作用。我不明白为什么你不能这样做,但这似乎是迫使我实施程序而不是很好地构建代码的方式。
LMK 如果你找到办法。
注意:他们只有当你先分组然后做 where 时才有分组依据(where 在完整的分组元素上 table => 对我来说没有任何意义)
EF 核心中的 GroupBy 支持是个笑话。
这在 EF6 的服务器上运行完美
var nonUniqueGroups2 = db.Transactions.GroupBy(e => new { e.AccountId, e.OpeningDate })
.Where(grp => grp.Count() > 1).ToList();
在 EF 核心中,它会导致异常“无法转换给定的 'GroupBy' 模式。在 'GroupBy' 之前调用 'AsEnumerable' 以在客户端对其进行评估。”该消息具有误导性,请勿调用 AsEnumerable
,因为这应该在服务器上处理。
我找到了解决方法 here。额外的 Select
会有所帮助。
var nonUniqueGroups = db.Transactions.GroupBy(e => new { e.AccountId, e.OpeningDate })
.Select(x => new { Key = x.Key, Count = x.Count() })
.Where(x => x.Count > 1)
.ToList();
解决方法的缺点是结果集不包含组中的项目。
有一个 EF Core issue。请对其进行投票,以便他们真正解决这个问题。
//Model
public class Application
{
[Key]
public int ApplicationId { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime ConfirmedDate { get; set; }
public DateTime IssuedDate { get; set; }
public int? AddedByUserId { get; set; }
public virtual User AddedByUser { get; set; }
public int? UpdatedByUserId { get; set; }
public virtual User UpdatedByuser { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string TRN { get; set; }
public string EmailAddress { get; set; }
public string Address { get; set; }
public int ParishId { get; set; }
public Parish Parish { get; set; }
public int? BranchIssuedId { get; set; }
public BranchLocation BranchIssued { get; set; }
public int? BranchReceivedId { get; set; }
public BranchLocation BranchReceived {get; set; }
}
public async Task<List<Application>> GetApplicationsByNameAsync(string name)
{
if (string.IsNullOrEmpty(name))
return null;
return await _context.Application
.AsNoTracking()
.Include(app => app.BranchIssued)
.Include(app => app.BranchReceived)
.Include(app => app.Parish)
.Where(app => app.LastName.ToLower().Contains(name.ToLower()) || app.FirstName.ToLower()
.Contains(name.ToLower()))
.GroupBy(app => new { app.TRN, app })
.Select(x => x.Key.app)
.ToListAsync()
.ConfigureAwait(false);
}
上面的 GroupBy
表达式无法在 VS Studio 中编译。我的 objective 是 运行 按包含用户给定字符串的名称过滤结果的查询,然后它应该按类似的 TRN
数字对结果进行分组 returning 这些应用程序的列表到 return 查看。我想我真的很接近,但似乎无法弄清楚查询的最后一点。任何指导表示赞赏。
显示错误
InvalidOperationException: The LINQ expression 'DbSet<Application>
.Where(a => a.LastName.ToLower().Contains(__ToLower_0) || a.FirstName.ToLower().Contains(__ToLower_0))
.GroupBy(
source: a => new {
TRN = a.TRN,
app = a
},
keySelector: a => a)' 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 either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()
更新
似乎这肯定是由于自最近更新以来 .net 核心 3.x 和 EF 核心一起玩的方式发生了变化。我不得不使用 AsEnumerable()
而不是 ToListAsync()
将其更改为客户评估。 Steve py 给出的其余查询使用此方法。即使在阅读了文档之后我也不知道 groupby 在 LINQ 中是如何工作的,所以这对我帮助很大。然而,将查询带到客户端 eval 可能会出现性能问题。
基于此:
I want to group by TRN which is a repeating set of numbers eg.12345, in the Application table there may be many records with that same sequence and I only want the very latest row within each set of TRN sequences.
我相信这应该能满足您的需求:
return await _context.Application
.AsNoTracking()
.Include(app => app.BranchIssued)
.Include(app => app.BranchReceived)
.Include(app => app.Parish)
.Where(app => app.LastName.ToLower().Contains(name.ToLower()) || app.FirstName.ToLower()
.Contains(name.ToLower()))
.GroupBy(app => app.TRN)
.Select(x => x.OrderByDescending(y => y.CreatedAt).First())
.ToListAsync()
.ConfigureAwait(false);
GroupBy
表达式应该表示您要分组的依据。在您的情况下,TRN。从那里开始,当我们执行 select 时,x
表示每个 "group",其中包含属于每个 TRN 的 Enumarable 应用程序集。因此,我们使用 First
.
试一试。如果这不是您想要的,请考虑为您的问题添加一个示例集以及所需的输出与此处产生的输出/错误。
我遇到过类似的问题,我觉得它既有趣又愚蠢。似乎 EF 团队禁止在 GROUP BY 之前执行 WHERE,因此它不起作用。我不明白为什么你不能这样做,但这似乎是迫使我实施程序而不是很好地构建代码的方式。
LMK 如果你找到办法。
注意:他们只有当你先分组然后做 where 时才有分组依据(where 在完整的分组元素上 table => 对我来说没有任何意义)
EF 核心中的 GroupBy 支持是个笑话。
这在 EF6 的服务器上运行完美
var nonUniqueGroups2 = db.Transactions.GroupBy(e => new { e.AccountId, e.OpeningDate })
.Where(grp => grp.Count() > 1).ToList();
在 EF 核心中,它会导致异常“无法转换给定的 'GroupBy' 模式。在 'GroupBy' 之前调用 'AsEnumerable' 以在客户端对其进行评估。”该消息具有误导性,请勿调用 AsEnumerable
,因为这应该在服务器上处理。
我找到了解决方法 here。额外的 Select
会有所帮助。
var nonUniqueGroups = db.Transactions.GroupBy(e => new { e.AccountId, e.OpeningDate })
.Select(x => new { Key = x.Key, Count = x.Count() })
.Where(x => x.Count > 1)
.ToList();
解决方法的缺点是结果集不包含组中的项目。
有一个 EF Core issue。请对其进行投票,以便他们真正解决这个问题。