![](/img/trans.png)
[英]Use MemberExpression in Entity Framework query. Entity Framework IQueryable extension with MemberExpression
[英]Entity framework IQueryable extension methods do not work as a sub query
我喜歡在可能的情況下使用擴展方法編寫查詢。 所以以下是一個適合我的查詢:
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);
}
但是,當我在子查詢中使用擴展方法時,我收到以下消息:
LINQ to Entities無法識別方法'System.Linq.IQueryable`1 [eNotify.Domain.Models.User] IsActive(System.Linq.IQueryable`1 [eNotify.Domain.Models.User])'方法,以及此方法無法翻譯成商店表達。
以下是導致該消息的查詢:
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();
我究竟做錯了什么?
更新: Alexander Derck發布了一個運行良好的解決方案,但不如原始問題查詢那么好。 我和EF團隊一起提出了這個問題,經過調查他們想出了一個更優雅的解決方案。 我在下面發布了接受的答案。
我最終在GitHub上使用Entity Framework團隊提出了這個問題。 您可以在此處查看該主題,並詳細說明其發生的原因:
https://github.com/aspnet/EntityFramework6/issues/98
它似乎已被提出作為包含在EF 6.2中的建議,但在此之前,建議進行非常優雅的解決方案。 您可以在線程中閱讀它,但我已將其復制到此處以供快速參考。
這是原始查詢(由於在子查詢中使用IQueryable擴展方法而發生錯誤):
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();
我可以確認這種風格仍然只會導致數據庫往返一次。 將查詢分解為多個語句實際上也提高了許多地方的可讀性。
您可以User
內部靜態類為您的User
模型創建一個分部類:
partial class User
{
public static class Q
{
public static Expression<Func<User,bool>> IsStudent
{
return x => x.Type == (int)UserTypes.Student;
}
}
}
然后您的查詢將如下所示:
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()
};
它不像擴展方法那么優雅,但它應該做我認為的伎倆......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.