使用Linq to SQL进行多线程处理

时间:2011-01-05 15:15:05

标签: sql linq linq-to-sql parallel-processing

由于原始帖子(Multi-threading with Linq to SQL)已经变得很老了,我以为我会在类似主题上发布另一个问题。考虑一种场景,其中DomainService公开了许多方法来从SQL Server数据库中检索数据。显然,在多用户场景中,同时有多个请求进入,人们不得不期望this.DataContext并行使用,开发人员无需控制或额外的工作来处理这些多个请求。 那么,如果我将顺序LINQ查询放入Parallel.Invoke()中,所有地狱都会破坏,我会得到dreadded “已经有一个与此命令关联的开放DataReader必须先关闭。”< / em>错误......?

为了证明,这有效:

List<Data> retVal = new List<Data>();

retVal.AddRange(this.DataContext.Table1.Where(w=>w.A==1).Select(s=>new Data{f1=s.D}).ToList());
retVal.AddRange(this.DataContext.Table1.Where(w=>w.B==2).Select(s=>new Data{f1=s.D}).ToList());
retVal.AddRange(this.DataContext.Table1.Where(w=>w.C==3).Select(s=>new Data{f1=s.D}).ToList());

......但事实并非如此:

List<Data> retVal = new List<Data>();
Parallel.Invoke(
()=>retVal.AddRange(this.DataContext.Table1.Where(w=>w.A==1).Select(s=>new Data{f1=s.D}).ToList()),
()=>retVal.AddRange(this.DataContext.Table1.Where(w=>w.B==2).Select(s=>new Data{f1=s.D}).ToList()),
()=>retVal.AddRange(this.DataContext.Table1.Where(w=>w.C==3).Select(s=>new Data{f1=s.D})).ToList());

不要介意List不是线程安全的,因为错误来自SQL数据连接。

非常感谢任何见解和解释。

2 个答案:

答案 0 :(得分:10)

首先,澄清一下,这个问题与多线程而不是多用户有关。在多用户方案中,每个用户都有自己的DataContext实例,避免了共享实例周围的线程问题。

并行示例失败,因为DataContext不是线程安全的对象;它希望由单个线程使用,而不是由许多并行使用。这是与数据读取器相关的异常,因为DataContext的连接打开,当您尝试并行执行第二个语句时,使用数据读取器读取。

如果您尝试在多个线程中使用一个SqlConnection实例而没有任何序列化技术,那么同样的问题就会很明显。

答案 1 :(得分:8)

您不应跨线程共享DataContext。它本质上是不安全的。另外,DataContext s意味着每个工作单元使用一个(即每个对话一个)。每个请求都应被视为不同的对话,并应使用唯一的DataContext进行回答。