我有一个拥有许多角色的用户.用户使用链接实体表链接到角色.我已将配置文件设置为在删除用户时级联删除用户角色链接实体.
我们目前正在使用软删除来删除实体.我们添加了一个由删除触发的软删除事件监听器.删除实体时,会触发DeleteEntity
将实体标记为已删除的事件.
我们还有一个覆盖OnPostUpdate
事件,通过在实体上调用Evict来从缓存中删除实体.
如果我创建一个没有任何角色的用户,那么删除它,一切正常(如果级联禁用,它也可以工作).但是,如果我有一个至少分配了一个角色的用户并且我删除了用户,则在调用Evict后OnPostUpdate
,我得到一个NHibernate异常"NHibernate.AssertionFailure:可能的非线程安全访问会话".
我已尝试OnPostUpdate
使用子会话来驱逐实体,但不会抛出异常,但实体不会被驱逐.
public void UserDelete(.....)
{
var user = repository.Fetch<User>(id);
repository.Remove(user);
repository.Connection.Commit();
}
// soft delete event listener
protected override void DeleteEntity(NHibernate.Event.IEventSource session, object entity, ..)
{
var repositoryEntity = entity as deletableentity;
if (repositoryEntity != null)
{
if (!repositoryEntity.IsDeleted)
{
// this marks the entity as deleted
repositoryEntity.isDeleted = true;
// cascade delete
this.CascadeBeforeDelete(session, persister, repositoryEntity, entityEntry, transientEntities);
this.CascadeAfterDelete(session, persister, repositoryEntity, transientEntities);
}
}
}
public void OnPostUpdate(PostUpdateEvent @event)
{
if (@event == null) throw new ArgumentNullException("event");
var entity = @event.Entity as deletableentity;
// Evict any entities that have been set as deleted from first level cache.
if (entity != null && entity.IsDeleted)
{
@event.Session.Evict(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
关于如何解决它的任何想法?
rog*_*ack 13
根据https://forum.hibernate.org/viewtopic.php?p=2424890另一种避免这种情况的方法是基本上打电话
session.save(s);
session.flush(); // allow evict to work
session.evict(s);
Run Code Online (Sandbox Code Playgroud)
并且问题的根源在于"如果我从缓存中驱逐实体,则commit()将不会在那里找到它"(即它根本不是线程安全问题,它是缓存被修改的问题).
找到问题所在了。使用软删除实际上会触发更新以设置 isDeleted 标志。由于映射中的这一行
cascade="all"
Run Code Online (Sandbox Code Playgroud)
级联适用于更新和驱逐操作。我的 postUpdate 将被触发 2 次,但同时 Evict 将尝试驱逐子实体。
解决方案是从映射文件中的级联中删除 Evict。现在它是:
cascade="persist, merge, save-update, delete, lock, refresh"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
15836 次 |
最近记录: |