c# - 在 EF Core 中加载集合项 (OwnsMany)

标签 c# entity-framework orm entity-framework-core

如何查询和过滤由 OwnsMany 为其所有者配置的集合属性中的数据功能?

这是我试过的示例:

using (var context = new BloggingContext())
{
    context.Database.OpenConnection();
    context.Database.EnsureCreated();

    context.Blogs.Add(sampleBlog);
    context.SaveChanges();

    var blog = context.Blogs.Single(b => b.BlogId == 1);

    var goodPosts = context.Entry(blog)
        .Collection(b => b.Posts)
        .Query()
        .Where(p => p.Title == "...")
        .ToList();
}

和模型类:

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

和 dbContext 类:

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>().OwnsMany(x => x.Posts, post =>
        {
            post.ToTable("Posts");
            post.HasKey("Id");

            post.Property(x => x.Title);
            post.Property(x => x.Content);
        });
        modelBuilder.Entity<Blog>()
            .ToTable("Blogs");
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connection = new SqliteConnection("Data Source=:memory:");
        optionsBuilder.UseSqlite(connection);
    }
}

我遇到了这个异常:

System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'

Inner Exception:

ArgumentException: Expression of type 'System.Collections.Generic.List`1[Post]' cannot be used for return type 'Post'

最佳答案

不幸的是,您遇到了 EF Core 错误/缺陷/问题,更具体地说,是在其针对自有实体类型集合的 Query() 方法实现中。

它可以在目前最新的官方 EF Core 3.1.7 版本和 EF Core 5 预览版中重现,因此值得向他们的 GitHub Issue Tracker 报告。 . Query() 之后的代码无关紧要,问题仅重现

context.Entry(blog).Collection(b => b.Posts).Query();

现在解决方法。有问题的方法主要用于显式加载。但是到自有实体类型的导航总是急切加载,这可能就是为什么他们在添加自有实体类型集合功能时错过了这种情况(它适用于常规的一对多导航和常规/自有引用导航)。不管是什么原因,在他们修复它之前,您不应该使用 Query() 方法,而应该使用 LINQ 手动编写查询。例如,使用以下等效于示例 Query 方法的方法:

context.Blogs.Where(b => b.BlogId == blog.BlogId).SelectMany(b => b.Posts)

但现在它强加了另一个错误/要求:

A tracking query projects owned entity without corresponding owner in result. Owned entities cannot be tracked without their owner. Either include the owner entity in the result or make query non-tracking using AsNoTracking().

因此您还需要将 AsNoTracking() 添加到您的 goodPosts 查询中。

或者,在这种特殊情况下,由于拥有的实体集合已经与所有者一起加载/跟踪,因此使用 LINQ to Objects 查询内存中的物化集合,这是通过替换 Query() 来实现的使用 CurrentValue:

var goodPosts = context.Entry(blog)
    .Collection(b => b.Posts)
    .CurrentValue
    .Where(p => p.Title == "...")
    .ToList();

或者直接使用导航属性:

var goodPosts = blog.Posts
    .Where(p => p.Title == "...")
    .ToList();

关于c# - 在 EF Core 中加载集合项 (OwnsMany),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63433515/

相关文章:

entity-framework - 如何处理 EF 4.1 运行时的动态连接字符串?

.net - 在哪里对实体运行重复检查

javascript - 用于 Javascript/JSON 的 ORM

java - 持久化对象在 Hibernate 架构中是什么意思?

c# - 如何顺序访问每个线程中的列表元素

c# - 无法解密 RSA 加密 key

c# - 我能否让 Entity Framework 使用具体类而不是接口(interface)(用于 Web 服务序列化)

c# - 为什么Wpf的DrawingContext.DrawText这么贵?

entity-framework - 如何在 ASP.NET 5 模板中添加实体数据模型

CakePHP 3. 可包含的选择