您的位置:首页 > 其它

不允许启动新事务,因为有其他线程正在该会话中运行(ef并发错误处理之一)

2013-08-14 10:35 453 查看
最近项目上线试运行过程中,总是遇到各种莫名其妙的问题,纠结了很久,今天就ef出现的“不允许启动新事务,因为有其他线程正在该会话中运行”这个错误,记录自己的解决方法。

当遇到这个问题的时候,在网上搜了很久,在这里还是要鄙视一下那些转载又不写出处的站长。

问题发现:

开始一直以为是数据库或者服务器的问题,因为用的是虚拟空间,很多设置没有办法改变。后来加入站长统计之后,发现pv量居然在200左右,突然意识到有可能是并发造成的。于是自己写了一段测试代码,该段代码的作用是模拟用户阅读新闻的时候,使新闻的阅读次数加1(只是改变字段的值,而不是新增一条浏览记录再去统计阅读次数)。代码如下:

public partial class WebForm1 : System.Web.UI.Page
{
delegate bool MyDelegate(Read info);

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ReadInfo ri = new ReadInfo ();

Read rad1 = ri.Get(1);
rad1.ReadTime += 1;

Read rad2 = ri.Get(1);
rad2.ReadTime += 1;

MyDelegate myDelegate = new MyDelegate(ri.Update);

myDelegate.BeginInvoke(rad1, null, null);
myDelegate.BeginInvoke(rad2, null, null);

Thread.Sleep(300);
}
}

}

public class ReadInfo
{
testEntities mytest = new testEntities();

public ReadInfo()
{
mytest.Read.MergeOption = System.Data.Objects.MergeOption.OverwriteChanges;
mytest.Read.EnablePlanCaching = false;
}

public Read Get(int Id)
{
return mytest.Read.SingleOrDefault(c => c.myId == Id);
}

public bool Update(Read Info)
{
int Result = 0;

if (mytest.Read.Count(c => c.myId == Info.myId) == 1)
{
Thread.Sleep(100);
Result = mytest.SaveChanges();
}

return Result > 0;
}
}


F10跟踪代码运行就报以下错误:



于是监控以下代码发现并发产生的时候,第一次是Modified,第二次却是Unchanged,所以当运行第二次更新的时候,则报错“不允许启动新事务,因为有其他线程正在该会话中运行”



所以最后解决此问题的方法就是将Update的代码改成:

public bool Update(Read Info)
{
int Result = 0;

if (mytest.Read.Count(c => c.myId == Info.myId) == 1)
{
if (Info.EntityState == System.Data.EntityState.Modified)
{
mytest.Refresh(RefreshMode.ClientWins, Info);
Thread.Sleep(100);
Result = mytest.SaveChanges();
}
}

return Result > 0;
}


虽然这样解决可以保证程序的稳定性,但是当并发发生的时候,阅读次数就不能+1了。不过阅读次数这个属性对于网站的数据而言并不是很重要,所以先这么解决着吧。如果是比较重要的属性,建议还是通过add方法去增加记录,而不是修改记录。或者通过用存储过程,将数据重新刷进表中,但是这样就缺乏实时性。

真是蛋痛的并发!以后再想想,看看有没有其他的解决办法吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐