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

By simon at 2018-02-28 • 0人收藏 • 44人看过

在以下博客中:该博客包含以下代码示例:

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的目的是什么?类? 它有什么影响?

6 个回复 | 最后更新于 2018-02-28
2018-02-28   #1

它允许实体框架围绕虚拟财产创建代理 以便该属性可以支持延迟加载和m矿石高效变化 跟踪。请参见[虚拟关键字在Entity Framework中可以产生什么效果 4.1 POCO Code First?](https://stackoverflow.com/questions/5597760/what- 效果 - 可以的虚拟关键字具有在实体框架-4-1 - poco代码fi)为 莫里斯彻底的讨论。 编辑以澄清“围绕创建代理”:通过“围绕创建代理”我是 特指wha实体框架确实如此。实体框架 要求你的导航属性被标记为虚拟的,以便懒惰 LOADI并支持有效的变更跟踪。见[要求 创建POCO代理](https://msdn.microsoft.com/en- 美国/升库/ dd468057 \(V = VS.100 \)。C ++)。 实体框架使用继承来支持这个功能 为什么要求es某些属性在您的基类中被标记为虚拟 波苏斯。它从字面上创建了从您的POCO t派生出的新类型伊普尔。所以 你的POOP动态地作为实体框架的基类型 创建子类。这就是我的意思是“c创建一个代理“。 动态创建的实体框架创建的子类成为 在使用实体时很明显y运行时的框架,而不是静态编译 时间。只有当你启用实体框架的延迟加载或更改 TRA特色。如果您选择不使用延迟加载或更改跟踪 实体框架的功能(这不是d默认),那么你不需要 将任何导航属性声明为虚拟。你是负责任的 用于加载这些naviga你可以使用什么实体 框架被称为“急切加载”,或者手动检索相关类型PES 跨多个数据库查询。你可以也应该使用延迟加载和 更改您的导航推荐的跟踪功能在很多情况下 虽然。 如果您要创建一个独立的类并将属性标记为虚拟,并且 简单地构造一个d在您自己的应用程序中使用这些类的实例, 完全超出了Entity Framework的范围,那么你的vir图阿尔 属性不会为你自己获得任何东西。 编辑来描述为什么属性会被标记为虚拟 Properties如:

 public ICollection<RSVP> RSVPs { get; set; }
不是田野,不应该这样想。这些被称为获得者 和制定者和compila它们被转换成方法。
//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;
这就是为什么它们被标记为虚拟以供在实体框架中使用Ť 允许动态创建的类覆盖内部生成的类 get和set功能。如果你的导航属性 getter / setters在你的Entity Framework用法中为你工作,试试 修改它们只是属性,重新编译并查看实体框架 能够正常工作:
 public virtual ICollection<RSVP> RSVPs;

2018-02-28   #2

它允许实体框架围绕虚拟财产创建代理 以便该属性可以支持延迟加载和m矿石高效变化 跟踪。请参见[虚拟关键字在Entity Framework中可以产生什么效果 4.1 POCO Code First?](https://stackoverflow.com/questions/5597760/what- 效果 - 可以的虚拟关键字具有在实体框架-4-1 - poco代码fi)为 莫里斯彻底的讨论。 编辑以澄清“围绕创建代理”:通过“围绕创建代理”我是 特指wha实体框架确实如此。实体框架 要求你的导航属性被标记为虚拟的,以便懒惰 LOADI并支持有效的变更跟踪。见[要求 创建POCO代理](https://msdn.microsoft.com/en- 美国/升库/ dd468057 \(V = VS.100 \)。C ++)。 实体框架使用继承来支持这个功能 为什么要求es某些属性在您的基类中被标记为虚拟 波苏斯。它从字面上创建了从您的POCO t派生出的新类型伊普尔。所以 你的POOP动态地作为实体框架的基类型 创建子类。这就是我的意思是“c创建一个代理“。 动态创建的实体框架创建的子类成为 在使用实体时很明显y运行时的框架,而不是静态编译 时间。只有当你启用实体框架的延迟加载或更改 TRA特色。如果您选择不使用延迟加载或更改跟踪 实体框架的功能(这不是d默认),那么你不需要 将任何导航属性声明为虚拟。你是负责任的 用于加载这些naviga你可以使用什么实体 框架被称为“急切加载”,或者手动检索相关类型PES 跨多个数据库查询。你可以也应该使用延迟加载和 更改您的导航推荐的跟踪功能在很多情况下 虽然。 如果您要创建一个独立的类并将属性标记为虚拟,并且 简单地构造一个d在您自己的应用程序中使用这些类的实例, 完全超出了Entity Framework的范围,那么你的vir图阿尔 属性不会为你自己获得任何东西。 编辑来描述为什么属性会被标记为虚拟 Properties如:

 public ICollection<RSVP> RSVPs { get; set; }
不是田野,不应该这样想。这些被称为获得者 和制定者和compila它们被转换成方法。
//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;
这就是为什么它们被标记为虚拟以供在实体框架中使用Ť 允许动态创建的类覆盖内部生成的类 get和set功能。如果你的导航属性 getter / setters在你的Entity Framework用法中为你工作,试试 修改它们只是属性,重新编译并查看实体框架 能够正常工作:
 public virtual ICollection<RSVP> RSVPs;

2018-02-28   #3

C#中的virtual关键字使方法或属性可以被覆盖 儿童班。欲了解更多信息,请参阅到[MSDN文档 '虚拟'关键字](http://msdn.microsoft.com/en- 我们/库/ 9fkccyh4%28V = VS.100%29.aspx) UPDATE:很明显,我的回答并不符合预期的结果 这个问题的情况,但我会留下它h为任何人寻找 对于一个简单的答案 [原创](https://stackoverflow.com/revisions/8542864/1),非描述性 阙stion问道。

2018-02-28   #4

我理解OP的挫败感,虚拟的这种用法不适合 模板抽象,事实上的虚拟修改器我对...有效。 如果任何人仍然在为此付出努力,那么我会试着提出我的观点 以保持解决方案简单和t他的行话至少是: 实体框架在一个简单的部分确实使用延迟加载,这是 相当于准备一些以备将来执行。这符合'虚拟' 修饰符,但还有更多。 在实体框架中,使用虚拟导航您可以使用gation属性来表示 它等同于SQL中的可空外键。你不必 热切地加入在执行查询时键入表,但是当您需要时 信息 - 它变成了需求驱动。 我也提到可空因为许多导航属性不相关 首先。即在客户/订单场景中,您不必等待直接升 订单处理以创建客户的时刻。你可以,但如果你有的话 一个多阶段的过程来实现这一点,你很高兴t找到需要坚持 客户数据用于稍后完成或部署到未来的订单。如果 所有导航属性已经实施,你必须建立每个外键 并保存关系字段。这真的只是设置数据back进入 记忆,这打破了持久性的作用。 所以虽然在运行时的实际执行过程中可能看起来很模糊,但我有found 使用的最佳经验法则是:如果您正在输出数据(阅读 到视图模型或序列化模型)和ne参考前的ed值 不使用虚拟;如果你的范围正在收集可能不完整的数据或者 需要搜索和不需要为搜索完成每个搜索参数, 该代码将很好地使用引用,类似于使用空值值 属性int?长?。此外,从数据中抽象出您的业务逻辑 收集,直到需要注入它有人y性能优势类似 实例化一个对象并在null处启动它。实体框架使用一个 很多反思d动态,这可能会降低性能,并且需要 有一个灵活的模型,可以扩展到需求是managin的关键G 性能。 对我而言,这总比使用超载的技术术语更有意义 代理人,代表,处理程序等。一旦你打你的第三或第四 编程语言,它可以让这些混乱。

2018-02-28   #5

在模型中定义导航属性是很常见的 虚拟。当导航属性被定义为虚拟时,它可以采取 某些实体框架功能的优势。最常见的是 延迟加载。

懒加载是一个nice许多ORM的功能,因为它可以让你 动态访问模型中的相关数据。它不会不必要地获取 Ť他将数据关联到实际访问数据,因此减少了前期 查询数据库中的数据。 从书“ASP.NET带有Bootstrap和Knockout.js的MVC 5“

2018-02-28   #6

在EF的上下文中,将属性标记为虚拟允许EF使用懒惰 加载加载它。懒惰加载工作EF哈s创建一个代理对象 使用加载的实现覆盖虚拟属性 当我参考实体时t首先被访问。如果您不将该物业标记为 虚拟,然后延迟加载将无法使用它。

登录后方可回帖

Loading...