【问题标题】:LINQ query throw exception on FirstOrDefault methodLINQ 查询在 FirstOrDefault 方法上引发异常
【发布时间】:2019-08-06 17:14:05
【问题描述】:

我正在使用 EF 核心,并且我在两个实体之间存在多对多关系

IotaProject 用户

这里是与问题相关的实体和 dto

public class IotaProject
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string ProjectName { get; set; }
    [Required]
    public DateTime Create { get; set; }

    public ICollection<ProjectOwnerJoint> Owners { get; set; } = new List<ProjectOwnerJoint>();

}

public class ProjectOwnerJoint
{
    public int IotaProjectId { get; set; }
    public IotaProject IotaProject { get; set; }

    public int UserId { get; set; }
    public User User { get; set; }

}

public class User
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string FullName { get; set; }
    [Required]
    public string ShortName { get; set; }
    [Required]
    public string Email { get; set; }

    public ICollection<ProjectOwnerJoint> OwnedProjects { get; set; } = new List<ProjectOwnerJoint>();
}

public class ApplicationDbContext : DbContext
{
    public DbSet<IotaProject> IotaProjects { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<ProjectOwnerJoint> ProjectOwnerJoint { get; set; }
}

public class IotaProjectDisplayDto
{
    public int Id { get; set; }
    public string ProjectName { get; set; }
    public DateTime Create { get; set; }

    public UserMinDto Owner { get; set; }
    public int Count { get; set; }

    public IEnumerable<UserMinDto> Reviewers { get; set; }
}

public class UserMinDto
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public string ShortName { get; set; }
}

下面是LINQ的问题,LINQ的目的是将IotaProject转换为IotaProjectDisplayDto,关键是IotaProject的Owners属性是ICollection,而IotaProjectDisplayDto的Owner属性只是一个元素 UserMinDto,所以我只需要获取 IotaProject 的 Owners 的第一个元素,那就是 FirstOrDefault() 来了。

IEnumerable<IotaProjectDisplayDto> results = _db.IotaProjects.Select(x => new IotaProjectDisplayDto
            {
                Id = x.Id,
                ProjectName = x.ProjectName,
                Create = x.Create,
                Owner = x.Owners.Select(y => y.User).Select(z => new UserMinDto { Id = z.Id, FullName = z.FullName, ShortName = z.ShortName }).FirstOrDefault()
            });
            return results;

它抛出运行时异常

Expression of type 'System.Collections.Generic.List`1[ToolHub.Shared.iota.UserMinDto]' cannot be used for parameter 
of type 'System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto]' 
of method 'ToolHub.Shared.iota.UserMinDto FirstOrDefault[UserMinDto](System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto])' (Parameter 'arg0')

我猜这可能与延迟执行有关,但看了一些帖子后,我仍然无法解决。

任何提示将不胜感激。

现在,我可以完成这项工作的唯一方法是将 IotaProjectDisplayDto 中的 Owner 属性类型更改为 IEnumrable,这将不再需要 FirstOrDefault() 来立即执行。后来,我手动让客户端中的第一个元素显示。

【问题讨论】:

  • 示例 LINQ 查询与异常之间存在差异。异常消息是指FirstUserMinDto 方法的List&lt;UserMinDto&gt; 参数,我在查询中没有看到。请提供重现问题的真实样本。
  • 抱歉,打错了,已经更新了。
  • 示例 LINQ 查询会导致 N + 1 个 SQL 查询,但不会重现异常。可能与 EF Core 版本有关 - 我使用的是最新的稳定版 2.2.6,您使用的 EF Core 的确切版本是什么?
  • 对你来说太糟糕了,因为很多东西在预览版中不起作用。您应该使用最新的稳定版 2.x 并等待 3.0 版本。
  • @IvanStoev 神圣...我最终按照您的建议将 EF 核心从 preview7 降级到 2.2.6,一切正常...非常感谢您指出这一点

标签: entity-framework-core linq-to-entities


【解决方案1】:

此问题发生在 Microsoft.EntityFrameworkCore.SqlServer 3.0.0-preview7.19362.6 中

正如 Ivan 在评论中建议的那样,我最终降级到 EF core stable 2.2.6,一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-25
    • 2018-06-17
    • 2014-12-18
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2022-08-15
    相关资源
    最近更新 更多