一尘不染

使用Linq to SQL进行多线程

sql

由于原始线程(使用Linq to
SQL的多线程
)到现在已经很老了,我想我会在类似的主题上发布另一个问题。考虑一个方案,其中DomainService公开了许多方法来从SQL
Server数据库检索数据。显然,在多用户方案中,同时有多个请求,人们必须期望this.DataContext可以并行使用,而开发人员无需控制也无需付出额外努力来处理这些多个请求。因此,如果我将顺序的LINQ查询放入Parallel.Invoke(),结果将彻底松开,然后我得到的内容
是“已经有与此命令关联的打开的DataReader,必须先关闭它”。 错误 …?

为了证明这一点,它可以工作:

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数据连接。

任何见解和解释将不胜感激。


阅读 131

收藏
2021-05-23

共1个答案

一尘不染

首先,需要澄清的是,此问题与多线程而不是多用户有关。在多用户方案中,每个用户将拥有自己的DataContext实例,从而避免了共享实例周围的线程问题。

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

如果您尝试在不使用SqlConnection任何序列化技术的情况下跨多个线程使用一个实例,则同样的问题将很明显。

2021-05-23