在以下博客中:http : //weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with- entity- framework-4.aspx
该博客包含以下代码示例:
public class Dinner { public int DinnerID { get; set; } public string Title { get; set; } public DateTime EventDate { get; set; } public string Address { get; set; } public string HostedBy { get; set; } public virtual ICollection<RSVP> RSVPs { get; set; } } public class RSVP { public int RsvpID { get; set; } public int DinnerID { get; set; } public string AttendeeEmail { get; set; } public virtual Dinner Dinner { get; set; } }
virtual在类中定义属性时使用的目的是什么?它有什么作用?
virtual
它允许实体框架围绕虚拟属性创建代理,以便该属性可以支持延迟加载和更有效的更改跟踪。请参阅virtual关键字在Entity Framework 4.1 POCO Code First中可以起到什么作用?进行更彻底的讨论。
编辑以澄清“在周围创建代理”: 通过“在周围创建代理”,我指的是实体框架的功能。实体框架要求将导航属性标记为虚拟,以便支持延迟加载和有效的更改跟踪。请参阅创建POCO代理的要求。 实体框架使用继承来支持此功能,这就是为什么它要求在基类POCO中将某些属性标记为虚拟的原因。它从字面上创建从POCO类型派生的新类型。因此,您的POCO充当实体框架动态创建的子类的基本类型。这就是我“围绕周围创建代理”的意思。
当在运行时而非静态编译时使用Entity Framework时,Entity Framework创建的动态创建的子类变得很明显。并且仅当您启用实体框架的延迟加载或更改跟踪功能时。如果您选择不使用实体框架的延迟加载或更改跟踪功能(这不是默认设置),则无需将任何导航属性声明为虚拟。然后,您将负责自己加载这些导航属性,或者使用Entity Framework所谓的“紧急加载”,或者在多个数据库查询中手动检索相关类型。在许多情况下,您可以并且应该为导航属性使用延迟加载和更改跟踪功能。
如果要创建一个独立的类并将属性标记为虚拟,并且仅在完全属于Entity Framework范围之外的自己的应用程序中构造和使用这些类的实例,那么您的虚拟属性将不会给您带来任何好处拥有。
编辑以描述为什么将属性标记为虚拟的原因
属性例如:
public ICollection<RSVP> RSVPs { get; set; }
不是字段,也不应该这样考虑。这些被称为getter和setter,在编译时,它们被转换为方法。
//Internally the code looks more like this: public ICollection<RSVP> get_RSVPs() { return _RSVPs; } public void set_RSVPs(RSVP value) { _RSVPs = value; } private RSVP _RSVPs;
这就是为什么在Entity Framework中将它们标记为虚拟的原因,它允许动态创建的类覆盖内部生成的get和set函数。如果您的导航属性获取器/设置器在您使用Entity Framework时为您工作,请尝试将它们修改为仅属性,重新编译,然后查看Entity Framework是否仍然能够正常运行:
get
set
public virtual ICollection<RSVP> RSVPs;