有一个“设置”实体存储数据的路径。有些实体使用设置来构建其数据路径。
我想在更改设置时验证其他实体的路径,并在必要时重新保存它们。我是如何尝试的:
重叠
Interceptor并捕获事件OnFlushDirty,它允许您捕获所需属性的变化:var folderIndex = propertyNames.ToList().IndexOf(nameof(Folder)); if (folderIndex > -1 && previousState != null) { var previous = previousState[folderIndex] as string; var current = currentState[folderIndex] as string; if (previous != current) { var someEntities = session.Query<ISomeEntity>().Where(m => m.Setting == this).ToList(); foreach (var someEntit in someEntities) { someEntity.RefreshFolder(); } } }
计算结果是,由于更改在会话内部(已经在事务提交中),因此将自动获取更改。没有帮助。如果someEntity.RefreshFolder();添加session.SaveOrUpdate(someEntity)之后,奇迹不会发生,实体也不会被保存。
在外部,设置调用包含在事务中:
using (var tranc = session.OpenTransaction()) { try { session.SaveOrUpdate(setting); tranc.Commit(); } catch (System.Exception) { tranc.Rollback(); throw; } }如第 1 点所示,有
SomeEntity一个指向 的链接Setting,如果我尝试进行单独的交易,那么它会转到 SO,因为 保存的设置成为保存实体所必需的,它将导致再次保存实体。所有会话都启用了它
session.FlushMode = FlushMode.Commit,以便会话中的随机更改(例如,稍后通过异常验证)不会尝试将其保存到数据库中。
一般来说,我希望设置中更改文件夹的操作是事务性的,因为如果不是,那么您可以在事务完成后简单地执行相同的操作,而无需将它们相互链接,但是不再可能了以保证数据的有效性。
显然,在 call 之后
tranc.Commit();,不再可能添加对象以进行提交。从这里我们跳舞。使用它的主要原因
OnFlushDirty是实体中的更改跟踪器。也可以手动获取此信息:因此,每个
session.SaveOrUpdate(entity)变成那些。任何实体的保存调用现在
BeforeSave可以对任何其他实体进行类似的调用,并且适用于任何嵌套。InterceptorOnFlushDirty仍然需要它,因为 除了显式引起SaveOrUpdate的变化外,hiber 还捕捉到了隐含的变化。因此,有一个类似的调用,entity.BeforeSave(new ChangeTrackerArgs(currentState, previousState, propertyNames));这个调用将不再能够将实体添加到事务中,但如果它突然进入隐式保存,它仍然会在保存之前验证实体。除了上述之外,虽然这与问题无关。hibera 中的更改跟踪器在会话上工作,因此对于正常操作,它需要在特定会话中获取一个实体,然后对其进行更改。如果在一个会话中接收到一个实体并尝试在另一个会话中保存,则跟踪器将为空,即 上面所有的折磨都不是很有用。