c# - 存储库模式:如何在基于过滤器的更新/删除时跟踪实体状态?
问题描述
我正在与工作单元一起实现存储库模式(通过 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);
问题是我无法跟踪更改的实体,因为我对将通过过滤器的实体一无所知。
我可能还必须支持通过过滤器更新部分实体。
如果可能的话,这样做的正确方法是什么?
解决方案
我不知道通过完全尊重UoW来实现批量删除(有条件或无条件)和批量更新(有条件或无条件)功能的ORM。是的; 许多 ORM 支持这些特性;但在这种情况下,UoW 不会被授予或部分被授予。是的,数据库操作将仅在刷新时执行(如您所说);但是内存中的副本或内存中的状态不能保证与底层 RDBMS 处于一致的状态。SaveChanges()
这是有原因的。要使 UoW 工作,必须将实体加载到内存中。对于上述情况,不能保证这一点。使这两个功能在 UoW 下工作的唯一方法是在后台将这些实体加载到内存中(如果尚未加载),然后执行操作。这将是非常低效的。许多 ORM 通过不遵守或部分遵守 UoW 来提供这两个功能。
关于部分实体更新,您必须跟踪属性(成员级别)的更改,而不仅仅是跟踪实体(类级别)的更改。
据我所知,有两种方法可以跟踪更改:
旗帜
您只需针对内存中实体的每个实例维护一些标志。如果对该特定实例执行任何操作,则相应地修改其相关标志。在刷新时,您只需检查此标志并根据其状态执行 CUD 操作。您无法使用这种方式跟踪成员级别的更改。
快照
通过这种方式,ORM 维护了实体最初加载时的副本。实际加载的实体被公开以进行更改。在刷新时,会根据原始副本检查实际实体。通过这种方式,您可以检测成员级别的更改。这里的内存和其他整体管理成本较高。
推荐阅读
- python - 一个点击计数器,显示您使用 python 3.8、tkinter、win32 和 pynput 单击左 mb 的次数
- ansible - 我如何在ansible中计算任务成功/失败?
- c# - C#:如何在 json 的引号内使用括号?
- c# - 使用 XMLReader 解析大 XML 文件
- java - 由于共享实例,Junit 测试失败(我认为)
- javascript - 使用脚本将 HSL 中的颜色列表转换为 RGB 作为 Google Apps 脚本
- asp.net-core - 大摇大摆地忽略一个动作的控制器路由路径
- linux - 创建一个包含样本、基因和行数的文件 - linux
- python - 如何装饰一个类,以便我能够在运行时更改类的属性
- dart - Dart - 在删除重复值的同时展平列表