1

我有一个多线程应用程序,它可能会同时插入一些具有标记为唯一属性的相同类型对象。

public class Foo(){
...
    string PropertyThatshouldBeUnique {get;set;}
...
}

每个线程都有自己的会话并执行以下操作:

Foo myFooInstance = new Foo();
myFooInstance.PropertyThatshouldBeUnique = "Bar";
myThreadSession.SaveOrUpadte(myFooInstance);
  • 我的数据库表有一个独特的约束,可以防止多次插入,因此我在第二次插入时遇到异常,触发整个事务的回滚(这不好)
  • 并发插入可能非常接近(几毫秒)
  • 我没有配置任何特定的Nhibernate 并发策略(不确定这是否可以解决我的问题或使用哪一个)

我的问题是:

我应该如何以及在代码中的何处检查先前插入的具有相同属性值的 Foo 对象?

4

2 回答 2

0

这是很久以前发布的,但是当我发现自己处于同样的情况时,让我告诉你我找到了哪些解决方案。

对于 DB 操作,它们不是让每个线程通过 来完成工作,而是Nhibernate将请求发送到另一个正在执行某种服务工作的线程。它公开了一些方法,如插入。

线程 1 想要插入 Object1

线程 2 想要插入 Object1

他们同时在做类似 Thread3.Insert(Object1) 的事情。

第一次调用Thread3接收,它打开一个到数据库的会话(无成本),它检查 Object1 不在数据库中SELECT,然后添加它。

第二个调用Thread3接收,即使是一纳秒后,它也会做同样的事情,但在之后停止SELECT并且什么也不做或发回异常。

等待第一个调用被处理的成本非常低,毕竟你通过需要检查的数据库约束来限制你的多线程速度(因此数据库访问)

这就像说,嗯,我有 2 台速度非常快的 PC 和 1 台低服务器。

我认为它更多的是设计问题而不是Nhibernate功能。

线程之间的同步已经很复杂了,但是使用 UnitOfWork 模式的线程之间的 DB 同步是一种痛苦。

(这是您的问题之一,因为您每次插入时都不会提交交易)

不过,也许这里的一些大师有更好的想法。

于 2014-01-17T13:58:14.593 回答
0

你能在 NHibernate 中做这样的事情而不破坏你当前的架构吗?

if(!Update(connection))
{
    using (var command = new SqlCommand(@"INSERT INTO foo VALUES (Bar, ...)", connection))
    {
        try
        {   
            command.ExecuteNonQuery(); 
        }               
        catch (BlahUniqueConstraintException) // dummy exception, please replace with relevant
        {
            // very rarely will get in here
            Update(connection);
        }           
    }
}           

private bool Update(SqlConnection connection)
{
    // use update to do two things at once: find out if the record exists and also ... update
    using (var command = new SqlCommand(@"UPDATE foo SET ... WHERE PropertyThatshouldBeUnique = 'Bar'", connection))
    {
        // if the record exists and is updated then returns 1, otherwise 0
        return command.ExecuteNonQuery() > 0;
    }   
}
于 2012-06-07T00:40:45.310 回答