2015-07-18 157 views
0

我有一個C#程序,它將數據庫中的產品列表加載到產品對象列表中。用戶可以通過我的程序界面添加新產品,編輯產品和刪除產品。相當標準的東西。我的問題涉及跟蹤這些更改並將其保存回數據庫。在瞭解細節之前,我知道使用Entity Framework或NHiberate之類的東西可以解決跟蹤添加和編輯的問題,但我認爲這不會解決跟蹤刪除的問題。除了想要將大型代碼轉換爲使用實體框架或NHiberate之外,我還想知道爲了我自己的好奇而回答這個問題。保存數據庫實體

爲了跟蹤編輯,我在做產品上的階級是這樣,我設置IsDirty標誌一個屬性更改的任何時間:

class Product 
{ 
    public bool IsDirty { get; set; } 
    public bool IsNew { get; set; } 

    // If the description is changed, set the IsDirty property 
    public string Description 
    { 
     get 
     { 
     return _description; 
     } 
     set 
     { 
     if (value != _description) 
     { 
      this.IsDirty = true; 
      _description = value; 
     }   
     } 
    } 
    private string _description; 

    // ... and so on 
} 

當我創建一個新的產品對象,我設置它的IsNew標誌,以便程序知道在下次用戶保存時將其寫入數據庫。一旦我成功將產品寫入數據庫,我就清除它的IsNew和IsDirty標誌。

爲了跟蹤其刪除,我做了一個列表類,跟蹤已刪除的項目:

class EntityList<T> : List<T> 
{ 
    public List<T> DeletedItems { get; private set; } 

    EntityList() 
    { 
     this.DeletedItems = new List<T>(); 
    } 

    // When an item is removed, track it in the DeletedItems list 
    public new bool Remove(T item) 
    { 
     this.DeletedItems.Add(item); 
     base.Remove(item); 
    } 
} 

// ... 

// When I work with a list of products, I use an EntityList instead of a List 
EntityList<Product> products = myRepository.SelectProducts(); 

每一次我的產品列表保存到數據庫中,我經歷了所有的產品在EntityList的迭代。 DeletedItems屬性並從數據庫中刪除這些產品。一旦列表成功保存,我將清除DeletedItems列表。

所有這些工作,但它似乎我可能做了太多的工作,特別是跟蹤刪除的項目,並記住每次創建一個新的產品對象時設置IsNew標誌。我無法在Product的構造函數中設置IsNew標誌,因爲如果從數據庫加載Product對象,我不想設置該標誌。我也不會感到興奮,因爲我必須在任何地方使用我的EntityList類而不是使用List。

看起來這種情況非常普遍,但我一直無法通過我的研究找到一種優雅的方式。所以我有兩個問題:

1)假設我沒有使用Entity Framework之類的東西,是否有更好的方法來跟蹤添加,編輯和刪除,然後將這些更改持久化到數據庫?

2)我是否正確地說,即使使用實體框架或NHiberate,我仍然必須編寫一些額外的代碼來跟蹤我的刪除項目?

回答

0

在EF中,DbContext對象包含所有跟蹤對其所知對象的更改的邏輯。如果可以SaveChanges它會計算出發生了哪些更改,並執行相應的操作將這些更改提交到數據庫。除了在要添加或刪除記錄時通知DbContext以外,您不需要執行與對象狀態相關的任何操作。

更新:

當查詢DbSet你獲得由EF內部跟蹤的對象。在SaveChanges期間,將這些對象的當前狀態與其原始狀態進行比較,並將那些已更改的對象放入隊列中以在數據中進行更新。

插入:

當您添加一個新的對象到相關DbSet它的SaveChanges通話過程中標記爲插入。該對象被登記在變更跟蹤,這是DB-生成的字段(例如自動遞增的ID)被更新等

刪除:

從數據庫中刪除記錄您對相關致電RemoveDbSet和EF將在下一個SaveChanges呼叫期間執行該操作。

因此,您不必擔心爲了數據庫而跟蹤這些更改,這些都是爲您處理的。您可能需要知道自己的利益 - 有時能夠爲更改顏色着色是很好的事情。

以上對於Linq2SQL以及其他可能的ORM和數據庫接口層也是如此,因爲它們的主要目的是允許您訪問數據,而無需編寫大量代碼來完成可以抽象的事情。

0
  1. 有沒有更好的方法來追蹤增加,編輯和刪除,然後堅持那些對數據庫的更改?

兩個Entity FrameworkNHibernate選擇不對實體本身負責通知,也沒有跟蹤其變化*。所以這不是一個不好的選擇。從設計模式的角度來看,它肯定是一個不錯的選擇(單一責任)。

它們分別存儲數據在上下文或會話中從數據庫加載時的快照。此外,這些快照有狀態說明它們是新的,更新的,刪除的還是未更改的。還有一些進程可以比較實際值和快照並更新實體狀態。當需要保存更改時,將評估狀態並生成適當的CRUD語句。

這一切都非常複雜,你自己實現。而且我甚至沒有提到實體國家的完整性及其相互關聯。但是,當然,這是可行的,一旦你決定遵循相同的模式。數據層通知/跟蹤更改(而不是實體本身)的優點是DAL知道哪些更改與數據存儲相關。並非所有屬性都映射到數據庫表,但實體不知道。

  1. 我仍然需要編寫一些額外的代碼來跟蹤我刪除的項目嗎?

號雙方或映射器具有持久性的無知的概念。您基本上只使用內存中的對象,可能會從列表中刪除它們(嵌套在所有者實體或表示數據庫表的列表中),並且ORM知道如何將實體的內存中狀態與數據庫同步。


*實體框架曾經有過自跟蹤實體,但他們被棄用。

+0

由於實體框架正在存儲我的數據的快照,這會產生多少開銷?它是否實質上存儲了每個對象兩次(當前的工作副本和原始副本),因此使用的內存量增加了一倍? –

+0

它將副本存儲爲值列表,工作副本是實現的對象以及您使用的對象。這是開銷嗎?這是整個過程中不可或缺的一部分。無論如何,總是建議使用短期的上下文(或會話),否則它們會變得非常沉重而且很慢。 –