首页 > 解决方案 > LINQ 实体框架查询在 EF Core 中不起作用,引发异常

问题描述

我有这个在旧应用程序中工作的实体框架 v4.0 查询,我正在将其转换为 EF Core 5.0 版。

当我在调试中运行代码时,它会在 .ToList(); 之后抛出以下错误。

The LINQ expression 'DbSet<User>()
    .GroupJoin(
        inner: DbSet<Address>(), 
        outerKeySelector: u => u.UserId, 
        innerKeySelector: a => a.UserId, 
        resultSelector: (u, ua) => new { 
            u = u, 
            ua = ua
         })' 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 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

所以,我添加了 .ToList() 并且还尝试了 .ToListAsync() 到查询的末尾,但是这个错误仍然存​​在。

我查看了 docs.microsoft 并发现这个示例看起来像我的查询

  var query = from person in people
                join pet in pets on person equals pet.Owner into gj
                from subpet in gj.DefaultIfEmpty()
                select new { person.FirstName, PetName = subpet?.Name ?? String.Empty }; 

更新:我注释掉了加入并删除了错误,但不知道为什么这不起作用。另一篇文章提到如果无法解释 linq 但附加连接看起来很简单,则会生成此错误,对吧?

 var users =
    
                        (from u in this.MyDbContext.User
                         join a in this.MyDbContext.Address
                                     on u.UserId equals a.UserId
                                     into ua
                         //join d in this.MyDbContext.JobTitle
                         //          on e.JobTitleId equals d.JobTitleId
                         from ua_left in ua.DefaultIfEmpty()
                         select new UserViewModel
                         {
                             BoardId = u.BoardId,
                             UserId = u.UserId,
                             LastName = u.LastName,
                             FirstName = u.FirstName,
                             JobTitleId = u.JobTitleId,
                             //JobTitle = d.JobTitleDescription,
                             Email = u.Email,
                             Grade = u.Grade,
                             Title = u.Title,
                             //StartDate = ua_left.StartDate,
                         });
  
      var test = users.ToList();

我不确定我错过了什么

var users =

                    (from u in this.MyDbContext.User
                     join a in this.MyDbContext.Address
                                 on u.UserId equals a.UserId
                                 into ua
                     join d in this.MyDbContext.JobTitle
                                 on e.JobTitleId equals d.JobTitleId
                     from ua_left in ua.DefaultIfEmpty()
                     select new UserViewModel
                     {
                         BoardId = u.BoardId,
                         UserId = u.UserId,
                         LastName = u.LastName,
                         FirstName = u.FirstName,
                         JobTitleId = u.JobTitleId,
                         JobTitle = d.JobTitleDescription,
                         Email = u.Email,
                         Grade = u.Grade,
                         Title = u.Title,
                         //StartDate = ua_left.StartDate,
                     });



  var test = users.ToList();

玩完代码后,如果我像这样取出左连接子句,查询将运行并返回数据

var users =

                    (from u in this.MyDbContext.User
                     join a in this.MyDbContext.Address
                                 on u.UserId equals a.UserId
                     join d in this.MyDbContext.JobTitle
                                 on e.JobTitleId equals d.JobTitleId
                     select new UserViewModel
                     {
                         BoardId = u.BoardId,
                         UserId = u.UserId,
                         LastName = u.LastName,
                         FirstName = u.FirstName,
                         JobTitleId = u.JobTitleId,
                         JobTitle = d.JobTitleDescription,
                         Email = u.Email,
                         Grade = u.Grade,
                         Title = u.Title,
                         //StartDate = ua_left.StartDate,
                     });



  var test = users.ToList();

我看了另一个帖子,其他人正在使用相同的左连接。我不确定为什么它不能在 EF Core 上运行。

任何帮助表示赞赏。谢谢。

标签: c#linqentity-framework-core

解决方案


虽然没有直接关系,但我相信是原因:EF Linq Error after change from dotnet Core 2.2.6 to 3.0.0


基本上,因为 EF Core 3 查询评估不再在客户端完成。这意味着,如果一个方法不能转换为 SQL 命令,它就会抛出异常。查看代码,它是DefaultIfEmpty()无法翻译的。编辑:还有多个连接into [x]似乎是不可翻译的。

您“可以”将表加载到内存中然后使用它 - 因为客户端/代码正在处理数据,而不是 EF 试图编译的 SQL 查询。但是,这会加载整个表格,这可能会非常密集 - 取决于大小。

更好的解决方案是使用空值 - 如下所示:(未测试

var users =
    (
        from u in this.MyDbContext.User
            join a in this.MyDbContext.Address
                on u.UserId equals a.UserId
            join d in this.MyDbContext.JobTitle
                on e.JobTitleId equals d.JobTitleId
        select new UserViewModel
        {
            BoardId = u.BoardId,
            UserId = u.UserId,
            LastName = u.LastName,
            FirstName = u.FirstName,
            JobTitleId = u.JobTitleId,
            JobTitle = d.JobTitleDescription,
            Email = u.Email,
            Grade = u.Grade,
            Title = u.Title,
            StartDate = 
                ua == null
                    ? System.Data.SqlTypes.SqlDateTime.MinValue
                    a.StartDate,
        }
    );

推荐阅读