Multithreading Nhibernate、多线程和竞争条件

Multithreading Nhibernate、多线程和竞争条件,multithreading,nhibernate,race-condition,Multithreading,Nhibernate,Race Condition,在使用NHibernate异步保存到数据库时,我遇到竞争条件问题。首先,在自动生成唯一id的情况下,异步完成对数据库的插入。在此插入操作返回到主线程之前,现在持久化的对象具有唯一的数据库生成id,该对象以某种方式更新。如果调用session.update,更新将失败,因为要更新的对象还没有id值。如果调用SaveOrUpdate,显然会导致插入而不是更新,因为实体的id字段等于unsaved value属性。希望这段代码能让情况更加清楚: Entity entity = new Entity()

在使用NHibernate异步保存到数据库时,我遇到竞争条件问题。首先,在自动生成唯一id的情况下,异步完成对数据库的插入。在此插入操作返回到主线程之前,现在持久化的对象具有唯一的数据库生成id,该对象以某种方式更新。如果调用session.update,更新将失败,因为要更新的对象还没有id值。如果调用SaveOrUpdate,显然会导致插入而不是更新,因为实体的id字段等于unsaved value属性。希望这段代码能让情况更加清楚:

Entity entity = new Entity()
//update some fields
entity.PropertyTwo = "new value";
//dataObject as the database auto-generated Id
//insert new row asynchronously in different thread
Entity entity.Id = dao.save(entity.Clone()).Id

//before the the entity is returned from the database, the entity might be updated
entity.Property = 'new value';
//entity might be sent without an Id since the first asynch call has not returned yet.
//update asynchronously in another thread
Object dataObject = dao.Update(entity); //fails because Id is not set yet

一种解决方案是在保存之前在代码中生成唯一id。在这种情况下,应用程序管理唯一id的递增,而不是数据库。处理此问题的任何其他方法?

看起来您可以在一个NHibernate会话中创建多个线程。NHibernate中的会话不是线程安全的。您不应该在两个并发线程中访问同一会话。尝试在新线程中创建一个单独的会话,看看它是否解决了您的问题


看看这本书

在调用update之前,需要放入某种“等待插入完成”类型的逻辑。这是标准的多线程异步编程

在多线程环境中,在同一对象上同时调用Insert和Update是非常可能的。您只需确保底层代码足够智能,以便:

  • 在更新之前执行插入
  • 等待插入完成后再开始更新
  • 有许多不同的方法可以做到这一点,其中没有一种方法一定比另一种更好。从概念上讲,您需要一个可以获取、放弃和等待的锁


    而且,这个问题实际上与NHibernate没有任何关系。多线程编程非常困难。如果可能的话,最好避免多线程,因为复杂性很容易失控。

    不,我正在为每个线程创建一个会话。如果在插入完成之前更新了实体上的更新,则会出现争用情况请记住,每个数据库调用都发生在不同的线程上,因此,如果在前一个线程上的插入完成之前在第二个线程上尝试更新,则会出现错误。请解释为什么要克隆实体对象并保存克隆您可能已经尝试过此操作,但是如果您在所有线程中为同一实体对象(无克隆)执行SaveOrUpdate(),则无论哪个线程先插入,其他线程都将执行更新。这对您的设计有用吗?我首先克隆实体对象,因为我要将它发送到另一个线程。我相信一般建议不要在线程之间共享对象。当你说你正在处理多个线程时,你怎么能说你在多个线程中没有使用同一个会话?