C# Linq调用-已经有一个与此命令关联的打开的DataReader,必须先关闭它
我有一些代码,当运行“EntityCommandExecutionException”类型的异常时会引发 Visual Studio指向的线:C# Linq调用-已经有一个与此命令关联的打开的DataReader,必须先关闭它,c#,linq,C#,Linq,我有一些代码,当运行“EntityCommandExecutionException”类型的异常时会引发 Visual Studio指向的线: else if (item.FirstOrDefault().InspectionEquipmentTypes.Any()) 例外情况的内部细节说明: There is already an open DataReader associated with this Command which must be closed first. 我的问题是引发
else if (item.FirstOrDefault().InspectionEquipmentTypes.Any())
例外情况的内部细节说明:
There is already an open DataReader associated with this Command which must be closed first.
我的问题是引发错误的那一行没有尝试使用数据库/数据读取器(据我所知),因此我不确定为什么会生成此异常
编辑:
当您以嵌套方式进行查询时,就会发生这种情况
item.FirstOrDefault().InspectionEquipmentTypes.ToList().Any()
可能有用。不过我不确定。尝试简化嵌套查询。例如,不要进行如下查询:
items.Where(/*some condition*/).Any();
取而代之的是制造
items.Any(/*some condition*/);
如果您真的想要嵌套查询(我不建议这样做,我宁愿使用一些散列数据结构进行单独的查询和链接实体),并且您使用的是sql server,那么您实际上有一个替代方案:激活MARS。要激活它,只需添加连接字符串MultipleActiveResultSets=True。有关更多详细信息,请访问此链接:下面是发生的情况:当您循环执行
批检查时,数据库读取器正在从数据库中读取此集合。在循环中,通过大量的First(OrDefault)
调用、Sum
和Count
执行新的数据库读取。这会导致异常“已存在打开的DataReader…”
正如George Lica所说,您可以通过在连接字符串中设置MultipleActiveResultSets=True
来解决这个问题
或者,您可以在循环开始创建之前,通过以下方式完成对批处理检查的读取:batchInspections
foreach (var item in batchInspections.ToList())
但是,首先收集您需要的数据,然后循环使用,效率要高得多:
foreach (var item in batchInspections
.Select(b => new
{
First = b.FirstOrDefault(),
Count = b.Count(),
Sum = b.Sum(s => s.Duration)
} )
.ToList())
{
var bigi = new BatchInspectionGridItem();
if (item.Any())
{
bigi.BatchInspectionNo = item.First.InspectionBatchNo;
if (item.First.EquipmentTypeID != null)
{
bigi.EquipmentTypeName = item.First.EquipmentType.Description;
}
else if (item.First.InspectionEquipmentTypes.Any())
{
bigi.EquipmentTypeName = string.Join(" / ", item.First.InspectionEquipmentTypes.Select(s => s.EquipmentType.Description));
}
bigi.CustomerName = item.First.CustomerSite.Customer.CustomerName;
bigi.CustomerID = item.First.CustomerSite.Customer.CustomerID;
bigi.NumberOfInspections = item.Count;
bigi.TotalDuration = item.Sum;
}
viewModel.BatchInspectionGridViewModel.Add(bigi);
}
我希望SchedulerManager.GetUnscheduledBatchInspections
返回一个IQueryable
,以便后续的Select
匿名类型将被转换为SQL
必须指出的是,激活MARS对于实体框架来说几乎总是一个好主意,因为延迟加载会导致这种异常。您可以发布更多的代码来显示项
是如何创建的吗?您在条件表达式中使用了LINQ。可以想象,以前的条件表达式将上下文绑定起来进行类似的检查。我猜您使用的是LINQtoSQL或LINQtoEntity框架。无论采用哪种方式,您都可以设置到数据库的连接,以允许多个活动结果集同时使用多个数据读取器。只需在连接字符串中添加以下内容:MultipleActiveResultSets=true;你能解释一下为什么是items.Where(“条件”).Any();比项目更糟糕。有任何(“条件”)?我猜.Any()只检查结果集,不运行额外的查询?虽然确实有技术上的好处,但我并不完全了解它们,但是增加可读性就足够了。
foreach (var item in batchInspections.ToList())
foreach (var item in batchInspections
.Select(b => new
{
First = b.FirstOrDefault(),
Count = b.Count(),
Sum = b.Sum(s => s.Duration)
} )
.ToList())
{
var bigi = new BatchInspectionGridItem();
if (item.Any())
{
bigi.BatchInspectionNo = item.First.InspectionBatchNo;
if (item.First.EquipmentTypeID != null)
{
bigi.EquipmentTypeName = item.First.EquipmentType.Description;
}
else if (item.First.InspectionEquipmentTypes.Any())
{
bigi.EquipmentTypeName = string.Join(" / ", item.First.InspectionEquipmentTypes.Select(s => s.EquipmentType.Description));
}
bigi.CustomerName = item.First.CustomerSite.Customer.CustomerName;
bigi.CustomerID = item.First.CustomerSite.Customer.CustomerID;
bigi.NumberOfInspections = item.Count;
bigi.TotalDuration = item.Sum;
}
viewModel.BatchInspectionGridViewModel.Add(bigi);
}