LINQ 多个“||”带“&”运算符
LINQ Multiple "||" with "&" operator
我有以下 Linq 查询试图过滤满足特定条件的结果集合,如下所示:
public async Task<BillListResponse> GetStudentCurrentBillsAsync(Student student)
{
var studentEvents = student.StudentEvents;
var studentServices = student.StudentServices;
var studentGroups = student.StudentGroups;
List<Bill> currentBills = await _context.Bills
.Include(b => b.Category)
.Where(b => ((b.ClassBills.Any(c => c.StudentClassId == student.ClassId)) || studentGroups.Any(sg => sg.SpecialGroupId == b.GroupId) || studentServices.Any(ss => ss.SpecialServiceId == b.ServiceId) || b.CareerPathBills.Any(cpb => cpb.CareerPathId == student.CareerPathId)) && b.SessionId == currentSession.Id
).ToListAsync();
......
但是我不断收到以下错误
InvalidOperationException: The LINQ expression 'DbSet
.Where(b => DbSet
.Where(c => EF.Property>(b, "Id") != null && EF.Property>(b, "Id") == EF.Property>(c, "BillId"))
.Any(c => c.StudentClassId == __student_ClassId_0) || __student_StudentEvents_1
.Any(se => (Nullable)se.EventId == b.EventId) || __student_StudentGroups_2
.Any(sg => (Nullable)sg.SpecialGroupId == b.GroupId) || __student_StudentServices_3
.Any(ss => (Nullable)ss.SpecialServiceId == b.ServiceId) || DbSet
.Where(c0 => EF.Property>(b, "Id") != null && EF.Property>(b, "Id") == EF.Property>(c0, "BillId"))
.Any(c0 => (Nullable)c0.CareerPathId == __student_CareerPathId_4) && b.SessionId == __currentSession_Id_5)' 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().
我没能解决。
但是,我意识到如果删除“||”表达式中的子句,如下:
List<Bill> currentBills = await _context.Bills
.Include(b => b.Category)
.Where(b => b.ClassBills.Any(c => c.StudentClassId == student.ClassId) && b.SessionId == currentSession.Id
).ToListAsync();
它有效,但我需要完整表达式中表达的更多条件。
我在 运行 ASP.NET-Core 3.1 Windows 上 SQL 服务器数据库。
“||”似乎有问题操作员。
请指导我解决这个问题。我会感激的。
谢谢
更新
实体关系如下:
学生实体有以下内容
public virtual ICollection<StudentGroup> StudentGroups { get; set; }
public virtual ICollection<StudentService> StudentServices { get; set; }
public virtual ICollection<StudentEvent> StudentEvents { get; set; }
并且还存在以下 DbSet
public DbSet<StudentGroup> StudentGroups { get; set; }
public DbSet<StudentEvent> StudentEvents { get; set; }
public DbSet<SpecialService> Services { get; set; }
而多对多中间表如下
public class StudentEvent
{
public string StudentId { get; set; }
public int EventId { get; set; }
[ForeignKey("StudentId")]
public Student Student { get; set; }
[ForeignKey("EventId")]
public SchoolEvent Event { get; set; }
}
public class StudentService
{
public int SpecialServiceId { get; set; }
public virtual SpecialService Service { get; set; }
public string StudentId { get; set; }
public virtual Student Student { get; set; }
}
public class StudentGroup
{
public int SpecialGroupId { get; set; }
public virtual SpecialGroup SpecialGroup { get; set; }
public string StudentId { get; set; }
public virtual Student Student { get; set; }
}
更新
我已经按如下方式修改了查询,它现在似乎可以正常工作了。
var studentEvents = student.StudentEvents.ToList();
var studentServices = student.StudentServices.ToList();
var studentGroups = student.StudentGroups.ToList();
List<Bill> bills = await (from b in _context.Bills where b.ClassBills.Any(c => c.StudentClassId == student.ClassId) || (studentEvents.Any() && studentEvents.Any(se => se.EventId == b.EventId)) || (studentGroups.Any() && studentGroups.Any(sg => sg.SpecialGroupId == b.GroupId)) || (studentServices.Any() && studentServices.Any(ss => ss.SpecialServiceId == b.ServiceId)) || b.CareerPathBills.Any(cpb => cpb.CareerPathId == student.CareerPathId) select b).ToListAsync();
另一种似乎按预期工作的方式如下
var studentEvents = student.StudentEvents.ToList();
var studentServices = student.StudentServices.ToList();
var studentGroups = student.StudentGroups.ToList();
var currentBills = _context.Bills
?.Include(b => b.Category)
?.Include(b => b.ClassBills)
?.Include(b=>b.CareerPathBills)
?.Where(b => b.SessionId == currentSession.Id);
if (student.StudentEvents.Any())
{
currentBills = currentBills.Where(b => student.StudentEvents.Any(se => se.EventId == b.EventId));
}
if (student.StudentServices.Any())
{
currentBills = currentBills.Where(b => student.StudentServices.Any(se => se.SpecialServiceId == b.ServiceId));
}
if (student.StudentGroups.Any())
{
currentBills = currentBills.Where(b => student.StudentGroups.Any(se => se.SpecialGroupId == b.GroupId));
}
var currentBillsList = await currentBills.ToListAsync();
和
currentBillsList
是 return
的预期结果
我不确定这是否是正确的方法。
失败的原因是 students
集合可能不是 SQL 数据库表查询的一部分,即调用 ToList
或 ToListAsync
它正在成为 C# 实体集合,不能与 LINQ to Entities 集合一起使用。
Hint: make sure that your students
are collections of IQuerable
.
但是,作为替代建议,您可以使用 Join
Students 和 Bills,而不是在 Where
子句中使用过滤。
我有以下 Linq 查询试图过滤满足特定条件的结果集合,如下所示:
public async Task<BillListResponse> GetStudentCurrentBillsAsync(Student student)
{
var studentEvents = student.StudentEvents;
var studentServices = student.StudentServices;
var studentGroups = student.StudentGroups;
List<Bill> currentBills = await _context.Bills
.Include(b => b.Category)
.Where(b => ((b.ClassBills.Any(c => c.StudentClassId == student.ClassId)) || studentGroups.Any(sg => sg.SpecialGroupId == b.GroupId) || studentServices.Any(ss => ss.SpecialServiceId == b.ServiceId) || b.CareerPathBills.Any(cpb => cpb.CareerPathId == student.CareerPathId)) && b.SessionId == currentSession.Id
).ToListAsync();
......
但是我不断收到以下错误
InvalidOperationException: The LINQ expression 'DbSet .Where(b => DbSet .Where(c => EF.Property>(b, "Id") != null && EF.Property>(b, "Id") == EF.Property>(c, "BillId")) .Any(c => c.StudentClassId == __student_ClassId_0) || __student_StudentEvents_1 .Any(se => (Nullable)se.EventId == b.EventId) || __student_StudentGroups_2 .Any(sg => (Nullable)sg.SpecialGroupId == b.GroupId) || __student_StudentServices_3 .Any(ss => (Nullable)ss.SpecialServiceId == b.ServiceId) || DbSet .Where(c0 => EF.Property>(b, "Id") != null && EF.Property>(b, "Id") == EF.Property>(c0, "BillId")) .Any(c0 => (Nullable)c0.CareerPathId == __student_CareerPathId_4) && b.SessionId == __currentSession_Id_5)' 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().
我没能解决。 但是,我意识到如果删除“||”表达式中的子句,如下:
List<Bill> currentBills = await _context.Bills
.Include(b => b.Category)
.Where(b => b.ClassBills.Any(c => c.StudentClassId == student.ClassId) && b.SessionId == currentSession.Id
).ToListAsync();
它有效,但我需要完整表达式中表达的更多条件。
我在 运行 ASP.NET-Core 3.1 Windows 上 SQL 服务器数据库。
“||”似乎有问题操作员。
请指导我解决这个问题。我会感激的。
谢谢
更新
实体关系如下:
学生实体有以下内容
public virtual ICollection<StudentGroup> StudentGroups { get; set; }
public virtual ICollection<StudentService> StudentServices { get; set; }
public virtual ICollection<StudentEvent> StudentEvents { get; set; }
并且还存在以下 DbSet
public DbSet<StudentGroup> StudentGroups { get; set; }
public DbSet<StudentEvent> StudentEvents { get; set; }
public DbSet<SpecialService> Services { get; set; }
而多对多中间表如下
public class StudentEvent
{
public string StudentId { get; set; }
public int EventId { get; set; }
[ForeignKey("StudentId")]
public Student Student { get; set; }
[ForeignKey("EventId")]
public SchoolEvent Event { get; set; }
}
public class StudentService
{
public int SpecialServiceId { get; set; }
public virtual SpecialService Service { get; set; }
public string StudentId { get; set; }
public virtual Student Student { get; set; }
}
public class StudentGroup
{
public int SpecialGroupId { get; set; }
public virtual SpecialGroup SpecialGroup { get; set; }
public string StudentId { get; set; }
public virtual Student Student { get; set; }
}
更新
我已经按如下方式修改了查询,它现在似乎可以正常工作了。
var studentEvents = student.StudentEvents.ToList();
var studentServices = student.StudentServices.ToList();
var studentGroups = student.StudentGroups.ToList();
List<Bill> bills = await (from b in _context.Bills where b.ClassBills.Any(c => c.StudentClassId == student.ClassId) || (studentEvents.Any() && studentEvents.Any(se => se.EventId == b.EventId)) || (studentGroups.Any() && studentGroups.Any(sg => sg.SpecialGroupId == b.GroupId)) || (studentServices.Any() && studentServices.Any(ss => ss.SpecialServiceId == b.ServiceId)) || b.CareerPathBills.Any(cpb => cpb.CareerPathId == student.CareerPathId) select b).ToListAsync();
另一种似乎按预期工作的方式如下
var studentEvents = student.StudentEvents.ToList();
var studentServices = student.StudentServices.ToList();
var studentGroups = student.StudentGroups.ToList();
var currentBills = _context.Bills
?.Include(b => b.Category)
?.Include(b => b.ClassBills)
?.Include(b=>b.CareerPathBills)
?.Where(b => b.SessionId == currentSession.Id);
if (student.StudentEvents.Any())
{
currentBills = currentBills.Where(b => student.StudentEvents.Any(se => se.EventId == b.EventId));
}
if (student.StudentServices.Any())
{
currentBills = currentBills.Where(b => student.StudentServices.Any(se => se.SpecialServiceId == b.ServiceId));
}
if (student.StudentGroups.Any())
{
currentBills = currentBills.Where(b => student.StudentGroups.Any(se => se.SpecialGroupId == b.GroupId));
}
var currentBillsList = await currentBills.ToListAsync();
和
currentBillsList
是 return
的预期结果我不确定这是否是正确的方法。
失败的原因是 students
集合可能不是 SQL 数据库表查询的一部分,即调用 ToList
或 ToListAsync
它正在成为 C# 实体集合,不能与 LINQ to Entities 集合一起使用。
Hint: make sure that your
students
are collections ofIQuerable
.
但是,作为替代建议,您可以使用 Join
Students 和 Bills,而不是在 Where
子句中使用过滤。