我有一个多线程应用程序,它可以对同一类型的对象进行一些并发插入,这些对象具有标记为唯一的属性。
public class Foo(){
...
string PropertyThatshouldBeUnique {get;set;}
...
}
每个线程都有自己的会话,并执行:
Foo myFooInstance = new Foo();
myFooInstance.PropertyThatshouldBeUnique = "Bar";
myThreadSession.SaveOrUpadte(myFooInstance);
我的问题是:
我应该如何以及在何处检查以前插入的具有相同属性值的Foo对象?
答案 0 :(得分: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;
}
}
答案 1 :(得分:0)
这是很久以前发布的,但是当我发现自己处于同样的情况时,让我告诉你我找到了什么解决方案。
对于数据库操作,不是让每个线程通过Nhibernate
完成工作,而是将它们的请求发送到另一个执行某种服务工作的线程。它暴露了一些像Insert这样的方法。
线程1想要插入Object1
线程2想要插入Object1
他们正在同时执行类似Thread3.Insert(Object1)的操作。
第一个调用Thread3
收到,它打开一个会话到DB(无成本),它检查Object1不在DB中SELECT
,然后添加它。
第二个调用Thread3
收到,即使它在一个纳秒之后,它会执行相同但在SELECT
之后停止并且不执行任何操作或发回异常。
等待处理第一个调用的成本非常低,毕竟您需要检查的数据库约束限制多线程速度(因此数据库访问)
就像说,嗯,我有2台非常快的PC和1台低服务器。
我认为它更像是一个设计问题,而不是Nhibernate
功能。
线程之间的同步已经很复杂了,但是在使用UnitOfWork模式的线程之间同步数据库是一件痛苦的事。
(这是你的问题之一,因为你每次插入时都不会提交你的交易)
也许这里的一些大师有更好的想法。