我记得在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 ICollectionPosts { 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 ICollectionEnrollments { get; set; } }
它不再需要了吗?
virtual
在EF 中从未被要求过.只有在您需要延迟加载支持时才需要它.
由于EF Core尚不支持延迟加载,因此目前 virtual
没有特殊含义.它会(以及如果)他们添加延迟加载支持(有一个这样做的计划).
更新:从EF Core 2.1开始,现在支持延迟加载.但是,只要您不添加Microsoft.EntityFrameworkCore.Proxies包并通过它启用它UseLazyLoadingProxies
,原始答案仍然适用.
但是,如果你这样做,由于初始实现中缺少选择加入控制,事情会完全改变 - 它需要 你所有的导航属性virtual
.这对我来说没有意义,你最好不要使用它,直到它得到修复.如果你真的需要延迟加载,请使用替代的Lazy加载而不使用代理
方法,在这种情况下再次virtual
无关紧要.
自从接受了答案后,情况发生了变化.在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 ICollectionPosts { 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
被要求当且仅当你想支持延迟加载与代理.否则,事实并非如此.
虚拟关键词从未被要求......它是可选的.
它有什么变化?
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;