我有一个C#程序,它将数据库中的产品列表加载到Product对象列表中。用户可以通过我的程序界面添加新产品,编辑产品和删除产品。很标准的东西。我的问题涉及跟踪这些更改并将其保存回数据库。在我了解详细信息之前,我知道使用Entity Framework或NHiberate之类的东西可以解决我关于跟踪添加和编辑的问题,但我认为这不会解决我跟踪删除的问题。除了想要将大型代码库转换为使用Entity Framework或NHiberate之外,我还想知道这个问题的答案是出于好奇心。
为了跟踪编辑,我在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)假设我没有使用像Entity Framework这样的东西,有没有更好的方法来跟踪添加,编辑和删除,然后将这些更改保存到数据库?
2)我是否正确地说,即使使用Entity Framework或NHiberate,我仍然需要编写一些额外的代码来跟踪我删除的项目?
答案 0 :(得分:0)
在EF中,DbContext
对象包含跟踪其所知对象更改的所有逻辑。如果可以SaveChanges
,它会确定发生了哪些更改,并执行相应的操作以将这些更改提交到数据库。您不需要对对象状态执行任何特定操作,只需在添加或删除记录时通知DbContext
。
更新
当您查询DbSet
时,您获得的对象将由EF内部跟踪。在SaveChanges
期间,将这些对象的当前状态与其原始状态进行比较,并将那些已更改的状态放入队列中以在数据中进行更新。
插入内容:
当您向相关DbSet
添加新对象时,会在SaveChanges
来电期间标记为插入。该对象注册在更改跟踪中,它更新了DB生成的字段(例如自动增量ID)等。
删除:
要从数据库中删除记录,请在相关Remove
上致电DbSet
,EF会在下一次SaveChanges
来电期间执行该操作。
因此,您不必为了数据库而担心跟踪这些更改,而是全部为您处理。您可能需要了解自己的好处 - 例如,能够为更改的记录着色有时很好。
对于Linq2SQL以及可能的其他ORM和数据库接口层也是如此,因为它们的主要目的是允许您访问数据而无需编写大量代码来执行可以抽象出来的操作。
答案 1 :(得分:0)
- 有没有更好的方法来跟踪添加,编辑和删除,然后将这些更改保存到数据库?
醇>
Entity Framework和NHibernate都选择不让实体负责通知或跟踪其变更 * 。所以这不是一个糟糕的选择。从设计模式的角度来看,它肯定是一个很好的选择(单一责任)。
它们分别在上下文或会话中从数据库加载数据时存储数据的快照。此外,这些快照还有状态,告知它们是新的,更新的,删除的还是未更改的。还有一些流程可以比较实际值和快照并更新实体状态。在保存更改时,将评估状态并生成适当的CRUD语句。
这一切都非常复杂,你自己实现。我甚至没有提到实体国家的完整性及其相互关联。但是,一旦你决定采用相同的模式,当然这是可行的。数据层通知/跟踪更改(而不是实体本身)的优点是DAL知道哪些更改与数据存储相关。并非所有属性都映射到数据库表,但实体不知道。
- 我还需要写一些额外的代码来跟踪我删除的项目吗?
醇>
没有。两个OR映射器都有持久性无知的概念。您基本上只处理内存中的对象,这可能包括从列表中删除它们(嵌套在所有者实体或表示数据库表的列表中),ORM知道如何将实体的内存中状态与数据库同步
* 实体框架曾用于自我跟踪实体,但已被弃用。