3

我在 nHibernate 上有一个竞争条件,它在我的数据库上创建了重复的条目。不幸的是,我无法UNIQUE在数据库上创建索引,因此我想仅使用 nHibernate 方法来解决此错误。它是一个可能在网络场上运行的网络应用程序(因此我猜系统锁也不应该解决问题)。简化的情况如下:

var current = UnitOfWorkManager.Instance.Current;
current.BeginTransaction(IsolationLevel.Serializable);
try {

    var myEntity = MyFactory.MyEntityRepository.GetBy(product, company);
    // race condition happens between the previous statement and Save() method.

    if (myEntity == null)
    {
      myEntity = new MyEntity();
      myEntity.Product     = product;
      myEntity.Company     = company;
      myEntity.Date        = date;
      myEntity.CurrentUser = currentUser;
      myEntity.IsManual    = true;
      myEntity.Save();
    }
    else
    {
      myEntity.IsManual    = false;
      myEntity.Save();
    }
    current.CommitTransaction();
}
catch {
    current.RollbackTransaction();
    throw;
}

我是 nHibernate 的新手,所以也许我在这里缺少一些基础知识。我会很感激任何反馈。:)

4

3 回答 3

1

阅读 nHibernate 手册后,我认为如果 subProjectToSupplier 不为空,您的问题可能是您第二次调用 save 。因为 nHibernate 手册说“保存”会插入。

尝试保存或更新

于 2013-07-11T14:59:54.310 回答
0

您应该将您Save()的事务包装在事务中,理想情况下您可以实现一个模式,例如IUnitOfWork或使用SessionFactory,例如:

using (var transaction = session.BeginTransaction()) {
  myEntity = new MyEntity();
  myEntity.Product = product;
  myEntity.Company = company;
  myEntity.Date = date;
  myEntity.CurrentUser = currentUser;
  myEntity.IsManual = true;
  myEntity.Save();
  transaction.Commit();
}
于 2013-07-09T09:01:58.540 回答
0

好的,所以你在这里要求 NHibernate 解决方案。我不确定这是否可以 100% 解决你的问题,但试试这个。

  1. 使用 ReadCommitted 隔离级别。
  2. 根据您的需要实施拦截器http://nhibernate.info/doc/nh/en/#manipulatingdata-interceptors

在拦截器中,您可以执行以下操作:

  1. 如果您的唯一列上有记录,请查询数据库。然后你可以应用某种合并机制
  2. 检查当前会话是否有像您这样的其他对象等待持久化。

=================

其他解决方案是保持场 (memcache) 之间的共享缓存并跟踪您不想复制的对象。

PS:我可以多谈谈每一点。告诉我是否有适合您的解决方案

于 2013-07-11T13:11:09.407 回答