【发布时间】:2012-12-26 07:37:39
【问题描述】:
我的应用程序有两个部分,它们分别执行大量插入和更新,并且由于管理不善或管理不善,出现了死锁。
我正在使用实体框架进行插入和更新。
以下是我的 TestSpool 程序的代码。该程序的目的是在给定的时间间隔内插入 x 条记录。
using System;
using System.Linq;
using System.Threading;
using System.Transactions;
namespace TestSpool
{
class Program
{
static void Main(string[] args)
{
using (var db = new TestEntities())
{
decimal start = 700001;
while (true)
{
using (TransactionScope scope = new TransactionScope())
{
//Random ir = new Random();
//int i = ir.Next(1, 50);
var objs = db.BidItems.Where(m => m.BidItem_Close == false);
foreach (BidItem bi in objs)
{
for (int j = 0; j <= 10; j++)
{
Transaction t = new Transaction();
t.Item_Id = bi.BidItemId;
t.User_Id = "Ghost";
t.Trans_Price = start;
t.Trans_TimeStamp = DateTime.Now;
start += 10;
db.Transactions.AddObject(t);
}
Console.WriteLine("Test Spooled for item " + bi.BidItemId.ToString() + " of " + 11 + " bids");
db.SaveChanges();
}
scope.Complete();
Thread.Sleep(5000);
}
}
}
}
}
}
程序的第二部分是testserverclass,该serverclass应该处理来自testspool的大量事务,并确定最大事务量并更新到另一个表。
using System;
using System.Linq;
using System.Transactions;
public class TestServerClass
{
public void Start()
{
try
{
using (var db = new TestServer.TestEntities())
{
while (true)
{
using (TransactionScope scope = new TransactionScope())
{
var objsItems = db.BidItems.Where(m => m.BidItem_Close == false);
foreach (TestServer.BidItem bi in objsItems)
{
var trans = db.Transactions.Where(m => m.Trans_Proceesed == null && m.Item_Id == bi.BidItemId).OrderBy(m => m.Trans_TimeStamp).Take(100);
if (trans.Count() > 0)
{
var tran = trans.OrderByDescending(m => m.Trans_Price).FirstOrDefault();
// TestServer.BidItem bi = db.BidItems.FirstOrDefault(m => m.BidItemId == itemid);
if (bi != null)
{
bi.BidMinBid_LastBid_TimeStamp = tran.Trans_TimeStamp;
bi.BidMinBid_LastBidAmount = tran.Trans_Price;
bi.BidMinBid_LastBidBy = tran.User_Id;
}
foreach (var t in trans)
{
t.Trans_Proceesed = "1";
db.Transactions.ApplyCurrentValues(t);
}
db.BidItems.ApplyCurrentValues(bi);
Console.WriteLine("Processed " + trans.Count() + " bids for Item " + bi.BidItemId);
db.SaveChanges();
}
}
scope.Complete();
}
}
}
}
catch (Exception e)
{
Start();
}
}
}
但是,由于两个应用程序同时运行,无论是从第一个测试应用程序还是服务器应用程序,它都会很快随机进入死锁。我如何优化双方的代码以防止死锁?我期待来自测试池应用程序的大量插入。
【问题讨论】:
-
首先,您能否暂时从服务器代码中删除 catch 块,看看会发生什么?到目前为止,您基本上有一个没有基本案例的服务器代码的递归方法。
另外,在您的客户端代码中,在事务范围完成后(在 using 语句结束后)设置睡眠,看看这对输出有何影响? -
如果没有服务器的try catch,应用程序都会遇到错误并死掉。
标签: c# sql entity-framework deadlock