分配谓词变量而不是 lambda 表达式
Assigning a predicate variable instead of a lambda expression
以下教科书连接查询运行良好:
var list = from family in db.Families.Where(f => !f.isDeleted)
join member in db.Members.Where(m => !m.isDeleted)
on family.Id equals member.FamilyID
select new { family = family.LastName, member = member.DisplayName };
list
是 IQueryable: {Microsoft.FrameworkCore.Query.Internal.EntityQueryable<<>f__AnonymousType0<string, string>>}
我可以调用 list.ToList()
.
但是,如果我在第一个 Where
中使用谓词,而不是使用 lambda,如下所示:
Predicate<Family> query = f => !f.isDeleted;
var list = from family in db.Families.Where(new Func<Family, bool>(query))
join member in db.Members.Where(m => !m.isDeleted)
on family.Id equals member.FamilyID
select new { family = family.LastName, member = member.DisplayName };
然后 list
变成 [IEnumerable]: {System.Linq.Enumerable.<JoinIterator>d__105<Family, Member, short, <>f__AnonymousType0<string, string>>}
并且结果视图抛出“已经有一个打开的 DataReader 与此连接关联,必须先关闭它。”。
我无法再重现它,但我确定有时结果视图会抛出“数据为空”异常。
我需要将过滤器设置为变量,因为所需的确切过滤器取决于其他一些条件。为什么使用 Predicate
赋值会导致 list
的类型不同,我该如何解决这个错误?
您正在调用 Where
的两个截然不同的重载。在第一个代码片段中,您正在调用:
Where<TSource>(IQueryable<TSource>, Expression<Func<TSource,Boolean>>
)
此重载将您的 lambda 表达式转换为 SQL 查询并在数据库上运行它。
在第二个代码片段中,您正在调用
Where<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>)
第二个重载是 LINQ to Objects Where
,它根本不知道您的数据库。它适用于所有 IEnumerable<T>
s.
您应该创建一个 Expression<Func<Family, bool>>
并将其传入:
Expression<Func<Family, bool>> query = f => !f.isDeleted;
var list = from family in db.Families.Where(query)
...
以下教科书连接查询运行良好:
var list = from family in db.Families.Where(f => !f.isDeleted)
join member in db.Members.Where(m => !m.isDeleted)
on family.Id equals member.FamilyID
select new { family = family.LastName, member = member.DisplayName };
list
是 IQueryable: {Microsoft.FrameworkCore.Query.Internal.EntityQueryable<<>f__AnonymousType0<string, string>>}
我可以调用 list.ToList()
.
但是,如果我在第一个 Where
中使用谓词,而不是使用 lambda,如下所示:
Predicate<Family> query = f => !f.isDeleted;
var list = from family in db.Families.Where(new Func<Family, bool>(query))
join member in db.Members.Where(m => !m.isDeleted)
on family.Id equals member.FamilyID
select new { family = family.LastName, member = member.DisplayName };
然后 list
变成 [IEnumerable]: {System.Linq.Enumerable.<JoinIterator>d__105<Family, Member, short, <>f__AnonymousType0<string, string>>}
并且结果视图抛出“已经有一个打开的 DataReader 与此连接关联,必须先关闭它。”。
我无法再重现它,但我确定有时结果视图会抛出“数据为空”异常。
我需要将过滤器设置为变量,因为所需的确切过滤器取决于其他一些条件。为什么使用 Predicate
赋值会导致 list
的类型不同,我该如何解决这个错误?
您正在调用 Where
的两个截然不同的重载。在第一个代码片段中,您正在调用:
Where<TSource>(IQueryable<TSource>, Expression<Func<TSource,Boolean>>
)
此重载将您的 lambda 表达式转换为 SQL 查询并在数据库上运行它。
在第二个代码片段中,您正在调用
Where<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>)
第二个重载是 LINQ to Objects Where
,它根本不知道您的数据库。它适用于所有 IEnumerable<T>
s.
您应该创建一个 Expression<Func<Family, bool>>
并将其传入:
Expression<Func<Family, bool>> query = f => !f.isDeleted;
var list = from family in db.Families.Where(query)
...