首页 > 解决方案 > 存储库模式:如何在基于过滤器的更新/删除时跟踪实体状态?

问题描述

我正在与工作单元一起实现存储库模式(通过 Mongo DB)。从存储库添加/更新/删除实体只需更新实体状态的内存(跟踪)列表,然后工作单元在其SaveChanges()方法中使用该列表在数据库上实际执行 CUD 操作。

例如Repository.Add()方法:

public void Add(TEntity entity)
{
    TrackingList[entity] = new EntityData<TEntity>(entity, EntityState.Added);
}

然后,在工作单元SaveChanges()实现中:

var addedEntities = repository.TrackingList.Values.Where(v => v.State == EntityState.Added).Select(v => v.Entity);
if (!addedEntities.Any())
    return;

// inserts the added entities to the Mongo DB collection
repository.Collection.InsertMany(addedEntities);

这在对特定实体显式执行 CUD 操作时有效。然后我可以管理这个跟踪列表。
但现在我正在尝试实现以下方法:

DeleteWhere(Expression<Func<Entity, bool>> filter);

问题是我无法跟踪更改的实体,因为我对将通过过滤器的实体一无所知。

我可能还必须支持通过过滤器更新部分实体。

如果可能的话,这样做的正确方法是什么?

标签: c#mongodbrepository-patterncrudunit-of-work

解决方案


我不知道通过完全尊重UoW来实现批量删除(有条件或无条件)批量更新(有条件或无条件)功能的ORM。是的; 许多 ORM 支持这些特性;但在这种情况下,UoW 不会被授予或部分被授予。是的,数据库操作将仅在刷新时执行(如您所说);但是内存中的副本或内存中的状态不能保证与底层 RDBMS 处于一致的状态。SaveChanges()

这是有原因的。要使 UoW 工作,必须将实体加载到内存中。对于上述情况,不能保证这一点。使这两个功能在 UoW 下工作的唯一方法是在后台将这些实体加载到内存中(如果尚未加载),然后执行操作。这将是非常低效的。许多 ORM 通过不遵守或部分遵守 UoW 来提供这两个功能。

关于部分实体更新,您必须跟踪属性(成员级别)的更改,而不仅仅是跟踪实体(类级别)的更改。

据我所知,有两种方法可以跟踪更改:

  1. 旗帜

    您只需针对内存中实体的每个实例维护一些标志。如果对该特定实例执行任何操作,则相应地修改其相关标志。在刷新时,您只需检查此标志并根据其状态执行 CUD 操作。您无法使用这种方式跟踪成员级别的更改。

  2. 快照

    通过这种方式,ORM 维护了实体最初加载时的副本。实际加载的实体被公开以进行更改。在刷新时,会根据原始副本检查实际实体。通过这种方式,您可以检测成员级别的更改。这里的内存和其他整体管理成本较高。


推荐阅读