簡體   English   中英

實體框架IQueryable擴展方法不能用作子查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM