ef-core-2.1 - 尽管急切获取 "attempt was made to lazy-load navigation property on detached entity"

标签 ef-core-2.1

我正在使用启用了延迟加载的 Entity Framework Core 2.1.2,并且正在使用 AsNoTracking 执行查询。我正在使用 Include 引入我的导航属性(一个集合)。

如果我的所有实体的集合中至少有一个 child ,那么一切正常。

但是,如果我的任何实体没有 child ,那么我会收到一个错误:

System.InvalidOperationException: Error generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.DetachedLazyLoadingWarning: An attempt was made to lazy-load navigation property 'Children' on detached entity of type 'ParentProxy'. Lazy-loading is not supported for detached entities or entities that are loaded with 'AsNoTracking()'.'



这是问题的再现(在使用 NuGet 引入 Microsoft.EntityFrameworkCore 2.1.2、Microsoft.EntityFrameworkCore.Proxies 2.1.2、Microsoft.EntityFrameworkCore.InMemory 2.1.2 后,它可以从控制台应用程序运行):
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace LazyLoadingIssue
{
    public class Parent
    {
        public int Id { get; set; }
        public string ParentName { get; set; }
        public virtual ICollection<Child> Children { get; set; }
    }

    public class Child
    {
        public int Id { get; set; }
        public int ParentId { get; set; }
        public virtual Parent Parent { get; set; }
        public string ChildName { get; set; }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            SetupDatabase(setupToFail: true);
            PerformTest();

            Console.WriteLine("Press any key to finish");
            Console.ReadLine();
        }

        private static void PerformTest()
        {
            using (var db = new MyContext())
            {
                try
                {
                    IQueryable<Parent> parents = db.Rounds.Include(r => r.Children).AsNoTracking();
                    foreach (Parent parent in parents)
                    {
                        Console.WriteLine($"Parent (Id={parent.Id}) '{parent.ParentName}'");
                        foreach (Child child in parent.Children)
                        {
                            Console.WriteLine($"  - Child (Id={child.Id}, ParentId={child.ParentId}) '{child.ChildName}'");
                        }
                    }

                    Console.WriteLine("** WORKED **");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("** FAILED **");
                    Console.WriteLine(ex);
                }
            }
        }

        private static void SetupDatabase(bool setupToFail)
        {
            using (var db = new MyContext())
            {
                db.Database.EnsureDeleted();
                db.Database.EnsureCreated();

                var parent1 = new Parent
                {
                    ParentName = "First sample parent (has children)",
                    Children = new List<Child>
                    {
                        new Child {ChildName = "child-1"},
                        new Child {ChildName = "child-2"},
                        new Child {ChildName = "child-3"}
                    }
                };
                var parent2 = new Parent
                {
                    ParentName = $"Second sample parent ({(setupToFail ? "with no children" : "has children")})",
                    Children = new List<Child>()
                };
                if (!setupToFail)
                    parent2.Children.Add(new Child {ChildName = "child-4"});
                db.AddRange(parent1, parent2);
                db.SaveChanges();
            }
        }
    }


    public class MyContext : DbContext
    {
        public DbSet<Parent> Rounds { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
//                .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=_ModelApp;Trusted_Connection=True;Connect Timeout=5;ConnectRetryCount=0")
                .UseInMemoryDatabase(databaseName: "_modelApp")
                .UseLazyLoadingProxies()
                ;
        }
    }

}

难道我做错了什么?或者这是 EF Core 中的错误? (我也发布了 an issue there。)

最佳答案

对于后代,这里是 response from the EF Core team :

This is because lazy-loading isn't supported for NoTracking queries (#10042) but we tried to not make it throw if it looked like lazy-loading wasn't needed. In retrospect it might have been better to always throw. Note that the warning can be configured to not throw using ConfigureWarnings in the DbContextOptionsBuilder.



以防万一它对某人有用,我最终做的是创建第二个“ReadOnlyRepository”,配置为不使用延迟加载并始终返回未跟踪的集合。我使用这个存储库进行查询,在这些查询中我永远不会保留对任何实体的更改,其中结果集可能很大并且何时需要良好执行。
public class ReadOnlyRepository : MainDbContextBase, IReadOnlyRepository
{
    public ReadOnlyRepository(IConfigurationSettings configurationSettings)
        : base(configurationSettings, false)
    {
    }

    public IQueryable<T> Retrieve<T>() where T : class, IAmAnAggregateRoot
    {
        return GetDbSet<T>().AsNoTracking();
    }
}

public class MainDbContextBase : DbContext
{
    private readonly IConfigurationSettings configurationSettings;
    private readonly bool useLazyLoading;

    protected MainDbContextBase(IConfigurationSettings configurationSettings, bool useLazyLoading)
    {
        this.configurationSettings = configurationSettings;
        this.useLazyLoading = useLazyLoading;
    }

    protected DbSet<T> GetDbSet<T>() where T : class
    {
        return Set<T>();
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder
                .UseLazyLoadingProxies(useLazyLoading)
                .UseSqlServer(configurationSettings.ConnectionString);
        }
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        ...
    }
}

}

关于ef-core-2.1 - 尽管急切获取 "attempt was made to lazy-load navigation property on detached entity",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52107513/

相关文章:

entity-framework - 属性X的类型为Y,当前数据库提供程序不支持该属性

entity-framework-core - 表达式中的EF Core 3 x.Contains(),其中x是ICollection

c# - 如何对 EF Core 2.1 中的继承列进行排序?

c# - 使用 EF Core 2.1 继承进行过滤

c# - ShadowProperties 在创建之前由 foreach 访问

ef-core-2.1 - 使用 EF core 2.1 调用 DbFunction

entity-framework-migrations - EF Core 空迁移问题

c# - 如何在 EF Core 2.1 中定义外键关系

c# - 找不到指定的框架 'Microsoft.NETCore.App',版本 '2.1'

oracle - oracle 数据库中特定表的脚手架 dbcontext 抛出与该表无关的错误