当前位置:  开发笔记 > 编程语言 > 正文

导航属性应该是虚拟的 - 在ef核心中不需要?

如何解决《导航属性应该是虚拟的-在ef核心中不需要?》经验,为你挑选了3个好方法。

我记得在EF 导航属性应该是虚拟的:

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

    public virtual ICollection Posts { get; set; }  
}

但我看看EF Core并不认为它是虚拟的:

public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }

        public ICollection Enrollments { get; set; }
    }

它不再需要了吗?



1> Ivan Stoev..:

virtual在EF 中从未被要求过.只有在您需要延迟加载支持时才需要它.

由于EF Core尚不支持延迟加载,因此目前 virtual没有特殊含义.它会(以及如果)他们添加延迟加载支持(有一个这样做的计划).

更新:从EF Core 2.1开始,现在支持延迟加载.但是,只要您不添加Microsoft.EntityFrameworkCore.Proxies包并通过它启用它UseLazyLoadingProxies,原始答案仍然适用.

但是,如果你这样做,由于初始实现中缺少选择加入控制,事情会完全改变 - 它需要所有的导航属性virtual.这对我来说没有意义,你最好不要使用它,直到它得到修复.如果你真的需要延迟加载,请使用替代的Lazy加载而不使用代理 方法,在这种情况下再次virtual无关紧要.


目前是(没有效果).它可能在未来.这就是重点.
@AntoinePelletier我也不知道 - 我根本不使用脚手架.但是要知道当前的EF Core状态 - 错误,不完整的功能,简单有效查询的奇怪内部异常,工具(特别是脚手架)对于使用它的人来说应该更少关注.
使用EF Core 1.X中的`Scaffold-DbContext`,所有导航属性都是虚拟的.升级到EF Core 2.X后,我只是重新搭建了架构,所有导航属性都不再是虚拟的.

2> Matt..:

自从接受了答案后,情况发生了变化.在2018年,对于两种不同的方法,现在支持实体框架核心2.1的延迟加载.

两者的简单方法是使用代理,这将需要延迟加载所需的属性来定义 virtual.要从链接页面引用:

使用延迟加载的最简单方法是安装Microsoft.EntityFrameworkCore.Proxies包并通过调用启用它UseLazyLoadingProxies.[...]然后,EF Core将为任何可以覆盖的导航属性启用延迟加载 - 也就是说,它必须是虚拟的,并且可以继承自可以继承的类.

以下是提供的示例代码:

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection Posts { get; set; }
}

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

    public virtual Blog Blog { get; set; }
}

还有另一种不使用代理进行延迟加载的方法,即注入ILazyLoader数据类型的构造函数.这在这里解释.

简而言之,有两种方法可以执行延迟加载:使用和不使用代理.virtual要求当且仅当你想支持延迟加载与代理.否则,事实并非如此.



3> Antoine Pell..:

虚拟关键词从未被要求......它是可选的.

它有什么变化?

1.如果您宣布您的财产是虚拟的:

查询主对象时,不会立即加载您的虚拟属性(默认情况下).只有当您尝试访问它或访问其中一个组件时,它才会从数据库中进行检索.

这称为延迟加载.

2.如果你声明它是非虚拟的:

您的财产将(默认情况下)立即加载到您的主要实体中的所有其他财产.这意味着您的财产将可以访问:它已经被检索.实体不必再次查询数据库,因为您访问此属性.

这被称为急切加载.

我的看法 :

更常见的是我选择急切加载(非虚拟),因为大多数时候,我需要使用每个实体的每个属性而不必回复(在你真的想要快速的一切的情况下更快)但是如果你访问这个属性只是偶尔(你没有列出任何东西)并且你想要更多的时候只是其余的信息只有这个,然后使它成为虚拟,所以这个属性不会减慢查询的其余部分只是为了一些访问.

希望这很清楚......

例子:

我不会使用虚拟(热切):

foreach(var line in query)
{
    var v = line.NotVirtual; // I access the property for every line
}

我将使用虚拟或延迟加载:

foreach(var line in query)
{
   if(line.ID == 509)        // because of this condition
   var v = line.Virtual; // I access the property only once in a while
}

最后一件事 :

如果您不查询超过1 000行数据库,那么您选择的任何内容都不会产生很大影响.此外,您可以将这些属性声明为虚拟,如果要进行相反的测试,则只需执行此操作(实体4.0):

context.LazyLoadingEnabled = false;

它将取消虚拟效果.

编辑

对于较新版本的EF:

WhateverEntities db = new WhateverEntities() 
db.Configuration.LazyLoadingEnabled = false;

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有