C# 实体框架IQueryable扩展方法不能作为子查询使用
我喜欢尽可能使用扩展方法编写查询。下面是一个对我有用的查询:C# 实体框架IQueryable扩展方法不能作为子查询使用,c#,entity-framework,linq,linq-to-sql,entity-framework-6,C#,Entity Framework,Linq,Linq To Sql,Entity Framework 6,我喜欢尽可能使用扩展方法编写查询。下面是一个对我有用的查询: int studentId = ( from u in db.Users .FromOrganisation(org.Id) .IsStudent() .IsActive() where u.ExtId == dto.StudentExtId select u.Id ).FirstOrDefault
int studentId =
(
from u in db.Users
.FromOrganisation(org.Id)
.IsStudent()
.IsActive()
where u.ExtId == dto.StudentExtId
select u.Id
).FirstOrDefault();
扩展方法如下:
public static IQueryable<User> IsStudent(this IQueryable<User> u)
{
return u.Where(x => x.Type == (int)UserTypes.Student);
}
我做错了什么
更新:
Alexander Derck发布了一个很好的解决方案,但没有原始问题查询那么好。我向EF团队提出了这个问题,在调查之后,他们提出了一个更优雅的解决方案。我已将此作为公认的答案发布在下面。您可以为您的
用户
模型制作一个包含静态类的部分类:
partial class User
{
public static class Q
{
public static Expression<Func<User,bool>> IsStudent
{
return x => x.Type == (int)UserTypes.Student;
}
}
}
它没有扩展方法那么优雅,但我认为它应该做到这一点……我最终在GitHub上的实体框架团队中提出了这一点。您可以在此处看到该线程,并对其发生的原因进行完整描述: 它似乎是作为一项建议被纳入EF 6.2的,但在此之前,人们提出了一个非常优雅的解决方案。你可以在帖子里读到它,但我把它复制到这里以供快速参考 以下是原始查询(其中由于子查询中使用IQueryable扩展方法而发生错误): 下面是如何编写它以避免出现错误:
var stuList = db.Users.FromOrganisation(org.Id).IsStudent().IsActive();
var staffList = db.Users.FromOrganisation(org.Id).IsStaff().IsActive();
var vm = from o in db.Organisations
select new StaffStudentVm
{
StudentId = (
from u in stuList
where u.ExtId == dto.StudentExtId
select u.Id
).FirstOrDefault(),
StaffId = (
from u in staffList
where u.ExtId == dto.StaffExtId
select u.Id
).FirstOrDefault()
};
return vm.FirstOrDefault();
我可以确认,这种样式仍然只会导致数据库的一次往返。将查询拆分为多个语句实际上也在很多地方提高了可读性。您可以链接您的
IsActive()
方法吗?根据错误消息,您可能正在执行无法转换为sql的操作。这不是IsActive方法。如果我在查询中对它进行注释,它只会报告下一个扩展方法作为问题。也许你可以使用表达式而不是扩展方法?你有一个例子吗?我在一个答案中写了一个例子,如果扩展方法不可能解决这个问题,那么它应该会起作用。我把它忘得一干二净,直到今天又碰到了同样的问题。这个解决方案非常有效。非常感谢。
var vm = from o in db.Organisations
select new StaffStudentVm
{
StudentId = (
from u in db.Users
.FromOrganisation(org.Id)
.Where(User.Q.IsStudent)
.IsActive()
where u.ExtId == dto.StudentExtId
select u.Id
).FirstOrDefault(),
StaffId = (
from u in db.Users
.FromOrganisation(org.Id)
.IsStaff()
.IsActive()
where u.ExtId == dto.StaffExtId
select u.Id
).FirstOrDefault()
};
var vm = from o in db.Organisations
select new StaffStudentVm
{
StudentId = (
from u in db.Users
.FromOrganisation(org.Id)
.IsStudent()
.IsActive()
where u.ExtId == dto.StudentExtId
select u.Id
).FirstOrDefault(),
StaffId = (
from u in db.Users
.FromOrganisation(org.Id)
.IsStaff()
.IsActive()
where u.ExtId == dto.StaffExtId
select u.Id
).FirstOrDefault()
};
return vm.FirstOrDefault();
var stuList = db.Users.FromOrganisation(org.Id).IsStudent().IsActive();
var staffList = db.Users.FromOrganisation(org.Id).IsStaff().IsActive();
var vm = from o in db.Organisations
select new StaffStudentVm
{
StudentId = (
from u in stuList
where u.ExtId == dto.StudentExtId
select u.Id
).FirstOrDefault(),
StaffId = (
from u in staffList
where u.ExtId == dto.StaffExtId
select u.Id
).FirstOrDefault()
};
return vm.FirstOrDefault();