C# EF Code First virtual关键字,它的作用是什么?

15
为什么我们在声明导航属性时需要使用"virtual"关键字?我知道Code First框架会以某种方式使用它来识别该属性为导航属性,但我想知道它是如何实现的。具体而言,我想知道它与MSDN文档中"virtual"关键字的描述有何关联:http://msdn.microsoft.com/en-us/library/9fkccyh4(v=vs.80).aspx

我认为你应该在这里阅读:https://dev59.com/FG035IYBdhLWcg3wJcjT - Denis Agarev
顺便说一下,你发的链接已经失效了。 - Anonymous
1
谢谢,我错过了“aspx”末尾的“x”。http://msdn.microsoft.com/en-us/library/9fkccyh4(v=vs.80).aspx - nckbrzg
2个回答

13
在运行时,Entity Framework将为您生成所谓的代理实体。这些实体是动态创建类型派生自您的实体类型的对象
这使您可以将您的实体用作POCO,这是一个简单的对象,与Entity Framework没有任何关系,因为它不继承自EntityObject
在运行时,动态创建的实体类型从您的POCO继承,并覆盖所有虚拟属性以添加Entity Framework的东西,以允许在属性getter中进行懒加载。
懒加载是一个复杂的过程,需要您的代码了解数据如何来自数据库。由于您不希望您的领域类知道数据库和EF的内容,因此将您的实体从EF中抽象出来并添加虚拟属性,因此EF可以在运行时覆盖您的基本POCO并添加其DB相关的内容。 更改跟踪也是一样的。

1

添加 virtual 允许 EF 生成一个派生类,该类覆盖属性并从数据库返回一个集合。


4
我认为解释这是为了惰性加载和/或更改跟踪会更好! - Matías Fidemraizer
啊,所以C#和Java处理被子类覆盖的属性的方式是一样的?也就是说,假设我声明了以下类:public class A { public string Foo = {get; set;} } 和public class B : A { public string Foo = {get; set;} }如果我执行以下操作:B bar = new B{"hello"};string test = ((A)bar).Footest会是null吗? - nckbrzg
1
@NicholasBranzburg:C#要求将属性指定为“virtual”才能被覆盖。你的示例无效,编译不通过。你需要这样做:public class A { public virtual string Foo { get; set; } public class B : A { public override string Foo { get; set; }。即使在这种情况下,你提出的操作((A)bar).Foo也会返回B.bar,因为它返回最具体的属性。 - Mike Bailey
@MikeBantegui 不是这样的,我刚试了一下。它可以编译通过。((A)bar).Foo 返回的是 A.Foo,就像我想的那样。如果你不相信,可以自己试一试。所以它实际上并没有覆盖它,只是将其粘贴在上面。从作为 B 创建的对象中访问 A.Foo 的唯一方法是将其转换为 A,否则你总是会得到 B.Foo。但你说的也对。如果你实际上尝试使用 override 关键字进行覆盖,你会得到一个编译器错误,这就是为什么你需要“virtual”关键字。 - nckbrzg

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