1

I'm trying to learn more about Entity Framework 5 and the DbContext, and I have a question about entity proxies.

Given a generated Alert entity class:

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; }
}

The following unit test code passes:

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);
}

I've looked around online to try and find a definitive explanation of what generated proxy objects actually do. Some questions I have:

  • As far as I can tell, the association property getter/setter is overridden. What logic is added here? Is anything else done in the proxy?

  • The debugger shows a field called _entityWrapper of type System.Data.Objects.Internal.EntityWrapperWithoutRelationships<System.Data.Entity.DynamicProxies.Alert_BF4E356370B8B5053A3384B5FAD30ECBA505359B71D47EBD90A674A9404D517C>. What is this for?

  • Will making attribute properties virtual do anything?

4

2 回答 2

2

来自Rowan Miller 在这个 MSDN 问题中的回答(重点是我的):

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

于 2013-07-25T21:01:12.867 回答
1

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

  1. 每当我们访问它时,我们都需要延迟加载来加载导航属性

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

所以尝试这样做,

alert.Title = "Changed title";
context.DetectChanges(); 
于 2013-07-23T11:07:47.520 回答