小编典典

为什么在实体框架模型定义中为类属性使用“虚拟”?

c#

在以下博客中: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在类中定义属性时使用的目的是什么?它有什么作用?


阅读 298

收藏
2020-05-19

共1个答案

小编典典

它允许实体框架围绕虚拟属性创建代理,以便该属性可以支持延迟加载和更有效的更改跟踪。请参阅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中将它们标记为虚拟的原因,它允许动态创建的类覆盖内部生成的getset函数。如果您的导航属性获取器/设置器在您使用Entity
Framework时为您工作,请尝试将它们修改为仅属性,重新编译,然后查看Entity Framework是否仍然能够正常运行:

 public virtual ICollection<RSVP> RSVPs;
2020-05-19