DbContext代理对象有什么意义?

时间:2013-07-23 10:41:53

标签: .net entity-framework entity-framework-5 dbcontext

我正在尝试了解有关Entity Framework 5和DbContext的更多信息,我对实体代理有疑问。

给定生成的Alert实体类:

public partial class Alert
{
    public Alert()
    {
        this.Readings = new HashSet<Reading>();
    }

    public int Id { get; set; }
    public string Title { get; set; }

    public virtual ICollection<Reading> Readings { get; set; }
}

以下单元测试代码通过:

using (var context = new MyContext())
{
    var alert = context.Alerts.Create();

    // Entity is a proxy
    Assert.AreNotSame(entity.GetType(), ObjectContext.GetObjectType(entity.GetType()));

    // Related entity collections are just HashSet<T>
    Assert.AreSame(typeof(HashSet<Reading>), alert.Readings.GetType());

    // Attach entity to the context
    context.Alerts.Attach(alert);

    var entry = context.ChangeTracker.Entries<Alert>().Single();

    // Initially it's unchanged
    Assert.AreEqual(EntityState.Unchanged, entry.State);

    // Change a property
    alert.Title = "Changed title";

    // However it's still unchanged
    Assert.AreEqual(EntityState.Unchanged, entry.State);
}

我在网上四处寻找,试图找到生成代理对象实际做什么的确切解释。我有一些问题:

  • 据我所知,关联属性getter / setter被覆盖。这里添加了什么逻辑?代理中还做了其他什么吗?

  • 调试器显示_entityWrapper类型为System.Data.Objects.Internal.EntityWrapperWithoutRelationships<System.Data.Entity.DynamicProxies.Alert_BF4E356370B8B5053A3384B5FAD30ECBA505359B71D47EBD90A674A9404D517C>的字段。这是为了什么?

  • 虚拟属性属性会做什么吗?

2 个答案:

答案 0 :(得分:2)

来自answer by Rowan Miller in this MSDN question(强调我的):

  

如果您将所有属性设置为虚拟,那么EF将在运行时生成源自您的POCO分类的代理类,这些代理允许EF实时查找有关更改而不必捕获您保存对象的原始值,然后在保存时扫描更改(这显然具有性能和内存使用效益,但除非您将大量实体加载到内存中,否则差异可以忽略不计)。这些被称为“更改跟踪代理”。 如果您[仅]使您的导航属性变为虚拟,则仍会生成代理,但它更简单,并且只包含一些逻辑,以便在您访问导航属性时执行延迟加载。

答案 1 :(得分:1)

EF使用代理对象动态跟踪更改并使用延迟加载。当我们将属性定义为虚拟EF时,可以覆盖它以支持这些行为。

  1. 我们需要延迟加载才能在我们访问时加载导航属性

  2. 动态更改跟踪,如果我们对属性进行一些更改,代理会立即将更改跟踪通知。如果我们不使用动态更改跟踪,则更改跟踪器需要在保存更改之前浏览所有属性,以发现更改。

  3. 所以试试这个,

    alert.Title = "Changed title";
    context.DetectChanges();