C# 在本地对查找公共项进行评估
使用Entity Framework Core 2.2,我有以下疑问:C# 在本地对查找公共项进行评估,c#,entity-framework-core,entity-framework-core-2.2,C#,Entity Framework Core,Entity Framework Core 2.2,使用Entity Framework Core 2.2,我有以下疑问: IQueryable<User> users = _context.Users.AsNoTracking(); User user = await users .Include(x => x.UserSkills) .ThenInclude(x => x.Skill) .FirstOrDefaultAsync(x => x.Id == 1); var userSkills = u
IQueryable<User> users = _context.Users.AsNoTracking();
User user = await users
.Include(x => x.UserSkills)
.ThenInclude(x => x.Skill)
.FirstOrDefaultAsync(x => x.Id == 1);
var userSkills = user.UserSkills.ToList();
IQueryable<Lesson> lessons = _context.Lessons.AsNoTracking();
var test = lessons
.Where(x => x.IsEnabled)
.Where(x => x.LessonSkills.All(y => userSkills.Any(z => y.SkillId == z.SkillId)))
.ToList();
如何更改查询以解决此问题
更新
我需要使用额外的选项(y.SkillLevelId x.IsEnabled)扩展此查询
.Where(x=>x.LessonSkills.All(y=>userSkills.Any)(z=>
y、 SkillId==z.SkillId
&&
y、 SkillLevelIduserSkills
是内存中的集合,根据我目前使用EF6和EF Core的经验,我可以说内存中集合的唯一可靠的可翻译构造是可枚举。包含内存集合中基元类型的
方法
所以下面解决的问题就是这个问题
首先(应该在查询表达式树之外):
而不是
.Where(x => x.LessonSkills.All(y => userSkills.Any(z => y.SkillId == z.SkillId)))
使用等效项(但可翻译):
更新:如果您不能使用包含,在EF Core开始支持它之前,您可以选择(1)包(我个人没有测试过,但想法很有趣),(2)使用表达式类手动构建或基于的谓词(很难,适用于小内存集合)和(3)例如,将内存集合替换为realIQueryable
var userSkills = users
.Where(x => x.Id == 1)
.SelectMany(x => x.UserSkills);
并使用原始查询。这是否回答了您的问题?否。错误“无法翻译,将在本地进行评估”是每次无法将Linq查询转换为SQL时发出的一般错误。您发布的问题与我的查询不同。错误可能相同,但导致错误的原因不同。我使用的是var userSkills=user.userSkills.ToList();
将userSkills作为内存集合作为解决此问题的原因…我也可以在查询中使用user.userSkills,但我也得到了一个例外。我知道您正在对UserSkill
对象进行内存集合。这就是问题所在,因为使用它的查询构造不会转换为SQL。而只选择ID和using包含
有效。建议的解决方案有什么问题,您尝试过吗?因为我在发布之前就尝试过,而且它对我有效(EF Core 2.2.6)。抱歉,由于缺少我提供的信息,您的答案有问题。如果您检查我刚才添加的更新,我还需要比较另一个属性:SkillLevel。因此包含将不起作用…我最初没有发布此内容,因为我想简化问题,不希望遗漏会影响答案。抱歉。@MiguelMoura我明白了。不幸的是,这是非常重要的细节,因为除Contains之外的任何内容都不能用于内存集合。
var userSkillIds = user.UserSkills.Select(x => x.SkillId);
.Where(x => x.LessonSkills.All(y => userSkills.Any(z => y.SkillId == z.SkillId)))
.Where(x => x.LessonSkills.All(y => userSkillIds.Contains(y.SkillId)))
var userSkills = users
.Where(x => x.Id == 1)
.SelectMany(x => x.UserSkills);