在Entity Framework Core中禁用延迟加载

20

有很多关于如何在Entity Framework中禁用延迟加载的帖子,但是相同的技术在EF Core中不起作用。我在更改跟踪器中找到了LazyLoadingEnabled属性,但这似乎根本不起作用。

在EF中,一切都指向这个:

this.Configuration.LazyLoadingEnabled = false;

但是,在EF Core中缺少Configuration属性。

以下是我所说的示例:

public class TestContext : DbContext
{
    public DbSet<Person> People { get; set; }
    public DbSet<Address> Addresses { get; set; }

    public TestContext()
    {
        this.ChangeTracker.LazyLoadingEnabled = false;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {            
        var connection = new SqliteConnection($"Data Source=Test.db");
        connection.Open();

        var command = connection.CreateCommand();

        command.CommandText = $"PRAGMA foreign_keys = ON;";
        command.ExecuteNonQuery();

        optionsBuilder.UseSqlite(connection);
        optionsBuilder.UseLazyLoadingProxies(false);

        base.OnConfiguring(optionsBuilder);
    }

    private static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

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

            var personKey = Guid.NewGuid().ToString();
            var addressKey = Guid.NewGuid().ToString();

            context.People.Add(new Entities.Person { PersonKey = personKey, BillingAddress = new Entities.Address { AddressKey = addressKey } });
            context.SaveChanges();
        }

        using (var context = new TestContext())
        {
            var people = context.People.ToList();

            foreach (var person in people)
            {
                if (person.BillingAddress == null) throw new Exception("The billing address wasn't loaded");
            }
        }
    }
}

尽管我已经关闭了延迟加载,但上述代码仍会抛出异常,因为 BillingAddress 没有被加载。

我怀疑这是一个 bug,但请告诉我不是。我已在这里记录了它:https://github.com/aspnet/EntityFrameworkCore/issues/15802

你可以在这里下载示例:https://www.dropbox.com/s/mimvgvcmibr7em2/EFSQLiteTest.7z?dl=0


3
关于"lazy loading off"的含义似乎存在一些混淆。当"lazy loading"关闭时,EF Core不会自动加载相关数据 - 你必须使用急切或显式加载来明确执行此操作。因此,异常是预期的,并证明了EF Core正在执行它应该做的事情。为了让EF Core在导航属性第一次访问时自动加载相关数据,你需要相反地打开"lazy loading"。 - Ivan Stoev
我已经尝试了两种方法,但都无法加载BillingAddress。没有办法加载所有子实体而不进行极端的修改。 - Christian Findlay
我不想使用懒加载。我想在一开始就加载所有实体。 - Christian Findlay
3
通常情况下,你不会希望急切地加载所有相关数据;大多数情况下,你只需要将整个数据库拉入本地内存即可。请记住,每次导航属性访问都会导致另一个(LEFT OUTER)连接,这会使查询非常缓慢,并且由于返回的行和列数量非常庞大,还会导致材料化。坦率地说,我认为这样的功能不应该存在,如果EF团队计划这样做,它应该需要奇怪的黑科技。你似乎对延迟加载和及早加载的区别感到困惑,你应该阅读相关资料。 - DevilSuichiro
@ChristianFindlay,你的期望与实际实现完全相反。 相信我们,我们曾经集体受过伤。 急切加载应始终通过显式的_Include_和_投影_来完成,这样默认实现就会自动高效,并且不太可能在将整个数据库加载到内存中时结束。 听起来你实际上想要懒惰加载,或者你希望编译器解析代码中所有可能的结果,以确定要加载到内存中的属性和记录,这只是懒惰的编程。 - Chris Schaller
显示剩余7条评论
1个回答

33

如果你的问题是如何在EF Core中禁用LazyLoading,请尝试:

this.ChangeTracker.LazyLoadingEnabled = false;

1
当我使用分层表时,暂时禁用惰性加载对我很有帮助;我一直收到“尝试惰性加载导航属性”的错误提示。 - Jeff
1
由于启动时间/配置时间启用了惰性加载,我曾经认为这个标志不存在了。非常感谢您纠正我的错误! - pbristow
EF Core 默认情况下是禁用懒加载的吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接