0

这是我的代码:

DatabaseDataContext context = new DatabaseDataContext();

var sourceList = (from q in context.Table1 where col1< 2000 select q).ToList();

foreach( Type x in sourceList)
{
    var task = Task.Factory.StartNew(() => FetchData(x));
}

FetchData(x)
{
    SomeBO obj = new SomeBO();

    obj.Prop1 = x.Table2.col;
    obj.Prop2 = x.Table3.col;
}

当我执行此代码时,我得到一个异常'已经有一个打开的 DataReader 与此命令关联,必须先关闭'。如何使方法“FetchData”为“sourceList”中的所有列表项并行执行?

4

3 回答 3

1

您在多个线程中使用一个上下文实例。但是上下文不是线程安全的。打开 MARS 将无济于事,任务将继续竞争连接。

解决方案是为每个任务创建一个新的上下文。也许像

FetchData(x)
{
    SomeBO obj = new SomeBO();
    using(var context = new DatabaseDataContext())
    {
        obj.Prop1 = context.Table2s.Where(t2 => t2.Id == x.Id)
                           .FirstOrDefault().col;
        ...
    }
}

但我不得不猜测,因为我不知道你的类的结构。

于 2013-05-24T13:49:38.043 回答
0

'There is already an open DataReader associated with this Command which must be closed first'

You could have a look at a link Entity Framework - There is already an open data reader associated with this command

How could I make the method 'FetchData' to execute in parallel for all the list item in 'sourceList'?

I think you want Parallel.ForEach

于 2013-05-24T09:15:31.403 回答
0

您正确地需要在您的连接字符串中包含MARS
像这样:

 var sqlBuilder = new SqlConnectionStringBuilder
          {
            DataSource = "myServer",
            InitialCatalog = "mydatabase",
            IntegratedSecurity = false,
            UserID = "user",
            Password = "pass",
            MultipleActiveResultSets = true //<-- here
          };

接着

   var efConnString = new EntityConnectionStringBuilder
          {
            ProviderConnectionString = sqlBuilder.ToString()
           //other properties omitted
          }

或者你可以用老式的方式来做:

string connectionString = "Data Source=MSSQL1;" + 
    "Initial Catalog=AdventureWorks;Integrated Security=SSPI" +
    "MultipleActiveResultSets=True";
于 2013-05-24T09:23:46.670 回答