LinqToSql.更新行时死锁.Parallel.For
本文关键字:Parallel For 死锁 更新 LinqToSql | 更新日期: 2023-09-27 18:18:44
我有一个问题。我正在尝试使用并行更新数据库。下面是代码:
Parallel.For(rCnt, range.Rows.Count + 1, (jrCnt, loopState) =>
{
var prcI = new Price(); // new
/*bla bla bla bla - bla bla - bla bla - bla */
if ((!string.IsNullOrEmpty(prcI.name)) && (prcI.prc != 0)) // process add or update
{
prcI.company = nameprice;
prcI.date = datatimeselect.Text;
Accessor.AddProductUpdateProduct(prcI); // main func
/*bla bla bla bla - bla bla - bla bla - bla bla - bla */
}
下面是要更新的函数代码字段:
public static bool AddProductUpdateProduct(Price price)
{
bool add = false;
var db = new PriceDataContext();
var matchedprod =
db.Price.Single(x => x.name == price.name && x.date != price.date && x.company == price.company); // find match
if (matchedprod != null) // match FOUnDE
{
if (matchedprod.prc != price.prc)
{
matchedprod.date = price.date;
matchedprod.prc = price.prc;
}
else
{
matchedprod.date = price.date;
}
db.SubmitChanges(); // DEADLOCK is her!!!
}
/*bla - bla bla - bla bla - bla bla - bla bla - bla */
}
当我创建一个记录,一切都很好!
谢谢!
记录计数在3000到10000之间(注释),我会在这里寻找一个解决方案,使用SqlBulkCopy将数据推入staging表(即一个表,看起来类似于你正在操作的数据,但不是你的核心模型的一部分)。这是向服务器获取大量数据的最有效的方法(尽管您可能还需要查看表值参数)。
有了服务器上的数据,我将执行一次更新(内部连接)和一次插入(不存在的地方),或单个"upsert"(在SQL server 2008及以上版本中可用)。
这会在应用服务器上使用更少的CPU、更少的网络和更少的数据库资源。而且,由于插入/更新中只涉及一个SPID,因此没有死锁的风险。
我想这可能是同样的问题,我在这个问题上描述的SELECT/UPDATE死锁。这不是linq to sql的问题。linq to sql的问题是,你不能很容易地用updlock执行select。