保存数据库实体

本文关键字:实体 数据库 保存 | 更新日期: 2023-09-27 18:03:36

我有一个c#程序,它将数据库中的产品列表加载到Product对象列表中。用户可以通过我的程序界面添加新产品、编辑产品、删除产品。非常标准的东西。我的问题与跟踪这些更改并将其保存回数据库有关。在我了解细节之前,我知道使用Entity Framework或nhibernate之类的东西会解决我关于跟踪添加和编辑的问题,但我不认为它会解决我关于跟踪删除的问题。除了想要将大型代码库转换为使用实体框架或nhibernate之外,我还想知道这个问题的答案,以满足我自己的好奇心。

为了跟踪编辑,我在Product类上做了这样的事情,在任何属性更改时设置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
}

当我创建一个新的Product对象时,我设置了它的IsNew标志,这样程序就知道下次用户保存时将它写入数据库。一旦我成功地将一个产品写入数据库,我就清除它的IsNew和IsDirty标志。

为了跟踪删除,我创建了一个List类来跟踪删除的项:

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列表。

所有这些都可以工作,但似乎我可能做了太多的工作,特别是跟踪已删除的项目,并记住每次创建新Product对象时设置IsNew标志。我不能在Product的构造函数中设置IsNew标志,因为我不想在从数据库加载Product对象时设置这个标志。我也不高兴,因为我必须在任何地方使用EntityList类,而不是使用List。

似乎这种情况非常普遍,但通过我的研究,我还没有找到一种优雅的方法来实现它。所以我有两个问题:

1)假设我不使用实体框架之类的东西,是否有更好的方法来跟踪添加,编辑和删除,然后将这些更改持久化到数据库?

2)我是否正确地说,即使在使用实体框架或nhibernate时,我仍然需要编写一些额外的代码来跟踪我删除的项目?

保存数据库实体

在EF中,DbContext对象包含跟踪它所知道的对象的更改的所有逻辑。当您可以执行SaveChanges时,它会找出发生了哪些更改,并执行适当的操作将这些更改提交到数据库。当你想要添加或删除记录时,你不需要对你的对象状态做任何特定的事情,而只是通知DbContext

更新:

当您查询DbSet时,您得到的对象由EF在内部跟踪。在SaveChanges期间,将这些对象的当前状态与它们的原始状态进行比较,并且将更改的对象放入队列中以便在数据中更新。

插入:

当你向相关的DbSet添加一个新对象时,它在SaveChanges调用期间被标记为插入。对象被登记在变更跟踪中,它的db生成的字段(例如自动增量id)被更新,等等。

删除:

要从数据库中删除一条记录,请在相关的DbSet上调用Remove, EF将在下一次SaveChanges调用时执行该操作。

因此,您不需要为数据库的缘故而担心跟踪这些更改,它已经为您处理好了。您可能需要了解自己的利益-例如,有时能够为更改的记录着色是很好的。

上述情况对于Linq2SQL以及其他orm和数据库接口层也是适用的,因为它们的主要目的是允许您访问数据,而无需编写大量代码来执行可以抽象出来的操作。

  1. 是否有更好的方法来跟踪添加、编辑和删除,然后将这些更改持久化到数据库中?

实体框架和NHibernate都选择不让实体自己负责通知或跟踪它们的更改*。所以这是个不错的选择。从设计模式的角度(单一职责)来看,这当然是一个很好的选择。

它们分别在上下文或会话中从数据库加载数据时存储数据的快照。此外,这些快照具有指示它们是新的、已更新的、已删除的还是未更改的状态。还有比较实际值和快照以及更新实体状态的过程。当需要保存更改时,将评估状态并生成适当的CRUD语句。

这些都是相当复杂的实现全部由你自己。我甚至没有提到实体国家的完整性和它们之间的相互联系。当然,这是可行的,只要你决定遵循同样的模式。数据层通知/跟踪更改(而不是实体本身)的优点是,DAL知道哪些更改与数据存储相关。不是所有的属性都映射到数据库表,但是实体并不知道。

  • 我仍然需要写一些额外的代码来跟踪我删除的项目?
  • 。两个OR映射器都有持久化忽略的概念。基本上,您只需处理内存中的对象,这可能包括从列表(嵌套在所有者实体中或表示数据库表的列表中)中删除它们,ORM知道如何将实体的内存状态与数据库同步。


    *Entity Framework过去有自跟踪实体,但已弃用。