2012-02-21 55 views
1

當我們的代碼只有一些實體的屬性被允許改變時,我們有一個場景。爲了保證這一點,我們有類似下面的代碼:強制實體框架返回一個新的實例

public void SaveCustomer(Customer customer) 
{ 
    var originalCustomer = dbContext.GetCustomerById(customer.Id); 

    if (customer.Name != originalCustomer.Name) 
    { 
     throw new Exception("Customer name may not be changed."); 
    } 

    originalCustomer.Address = customer.Address; 
    originalCustomer.City = customer.City; 

    dbContext.SaveChanges(); 
} 

這段代碼的問題是,調用dbContext.GetCustomerById總是不給我Customer類的新實例。如果客戶已經從數據庫中提取,Entity Framework會將實例保存在內存中,並在每次後續的調用時返回它。

這導致我們遇到了實際問題 - customeroriginalCustomer可能指的是同一個實例。在這種情況下,customer.Name將等於originalCustomer.Name,我們將無法檢測到它是否與數據庫不同。

我想大多數其他ORM也存在同樣的問題,因爲身份圖設計模式。

任何想法如何解決這個問題?我能以某種方式迫使EF永遠給我一個客戶類的新實例嗎?

或者我們應該重構代碼嗎?有沒有人知道這種情況下有什麼好的設計模式?

+0

GetCustomerById從哪裏來?另外,你的上下文的壽命是多少? – ken2k 2012-02-21 10:09:03

+0

啊,對不起。 GetCustomerById只是DbSet .Find()的包裝方法。生命週期是根據HTTP請求。 – jhu 2012-02-21 10:18:05

+0

如果你不希望'Name'被改變,只是不允許上層代碼與'Customer'實體一起工作(=創建新的類,其中'Name'將是隻讀的)或者隱藏setter。 – 2012-02-21 11:05:47

回答

1

您可以嘗試從上下文中分離實體,這將刪除對上下文的所有引用(以及身份映射行爲)。 因此,在將客戶傳遞給您的方法之前,您可以將其分離:

yourContext.Detach(customer); 
+1

這在技術上是正確的答案。如果你想從數據庫中得到新的實例,你必須首先從上下文中分離出先前的實例。 – 2012-02-21 11:04:32