Jam*_*mes 4 c# datacontext multithreading linq-to-sql
我正在构建一个应用程序,它要求我使用DataContext的内部线程.我的应用程序不断抛出InvalidOperationException
类似于:
There is already an open DataReader associated with this Command which must be closed first
ExecuteReader requires an open and available Connection. The connection's current state is connecting
这些例外是间歇性的.
这是我的代码片段:
var repo = new Repository();
var entities = repo.GetAllEntities();
foreach (var entity in entities)
{
ThreadPool.QueueUserWorkItem(
delegate
{
try
{
ProcessEntity(entity);
}
catch (Exception)
{
throw;
}
});
}
Run Code Online (Sandbox Code Playgroud)
我认为将一个实体传递给主线程中的一个线程可能会有一些问题,因为一旦我尝试访问一个属性,错误似乎就会抛出entity
.
任何人都知道为什么会发生这种情况以及如何解决它?
更新
这是我决定采用的:
var events = new Dictionary<int, AutoResetEvent>();
var repo = new Repository();
var entities = repo.GetAllEntities();
foreach (var entity in entities)
{
events.Add(entity.ID, new AutoResetEvent(false));
ThreadPool.QueueUserWorkItem(
delegate
{
var repo = new Repository();
try
{
ProcessHierarchy(repo.GetEntity(entity.ID), ReportRange.Weekly);
}
catch (Exception)
{
throw;
}
finally
{
events[entity.ID].Set();
}
});
}
WaitHandle.WaitAll(events.Values.ToArray());
Run Code Online (Sandbox Code Playgroud)
欢迎改进/建议,但这似乎已经成功了.
抛出异常,因为实体的某些属性在先前的读取器尚未关闭时执行新查询.您不能同时对数据上下文执行多个查询.
作为一种解决方法,您可以"访问"您访问的属性,ProcessEntity()
并在线程之前运行SQL.
例如:
var repo = new Repository();
var entities = repo.GetAllEntities();
foreach (var entity in entities)
{
var localEntity = entity; // Verify the callback uses the correct instance
var entityCustomers = localEntity.Customers;
var entityOrders = localEntity.Orders;
var invoices = entityOrders.Invoices;
ThreadPool.QueueUserWorkItem(
delegate
{
try
{
ProcessEntity(localEntity);
}
catch (Exception)
{
throw;
}
});
}
Run Code Online (Sandbox Code Playgroud)
此解决方法将仅在主线程上执行SQL,并且处理将在其他线程中完成.由于所有查询都在单个线程中完成,因此您在这里放松了一些效率.如果你有很多逻辑ProcessEntity()
并且查询不是很重,那么这个解决方案很好.