2013-07-23 46 views
1

我想了解更多關於實體框架5和DbContext,並且我有關於實體代理的問題。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被覆蓋。這裏添加了什麼邏輯?代理中是否還有其他工作要做?

  • 調試器顯示System.Data.Objects.Internal.EntityWrapperWithoutRelationships<System.Data.Entity.DynamicProxies.Alert_BF4E356370B8B5053A3384B5FAD30ECBA505359B71D47EBD90A674A9404D517C>類型的字段_entityWrapper。這個是來做什麼的?

  • 將使屬性屬性虛擬做任何事情?

回答

2

answer by Rowan Miller in this MSDN question(重點煤礦):

如果你把所有的屬性虛擬然後EF會在運行時生成的代理類來自您的POCO分類,這些代理允許EF實時查找變化,而不必捕獲對象的原始值,然後掃描f或者在保存時發生變化(這顯然具有性能和內存使用方面的好處,但除非將大量實體加載到內存中,否則差異可以忽略不計)。這些被稱爲「更改跟蹤代理」。 如果您[只]使您的導航屬性爲虛擬那麼代理仍然會生成,但它更簡單,只是包含一些邏輯來執行延遲加載,當您訪問導航屬性。

1

EF使用代理對象動態跟蹤更改並使用延遲加載。當我們將一個屬性定義爲虛擬EF時,它可以覆蓋它以支持這些行爲。

  1. 我們需要延遲加載加載導航屬性,每當我們訪問

  2. 動態變化的跟蹤,如果我們做一個屬性的一些變化,代理將立即通知到變更跟蹤。如果我們不使用動態更改跟蹤,則更改跟蹤器需要在保存更改之前遍歷所有屬性,以發現更改。

因此,嘗試這樣做,

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

通過關係的延遲加載似乎是合法的。但是,據我所知,動態更改跟蹤對於屬性不起作用。您顯示的代碼對於代理和非代理情況都是相同的。 –

+0

您需要將所有屬性定義爲虛擬,就像導航屬性一樣。 –

+0

在我的示例中將'Title'屬性定義爲'virtual'對我演示的測試用例的結果沒有影響。更改「標題」後,實體仍爲「未更改」。 –