我有一些代码在运行“EntityCommandExecutionException”类型的异常时被引发。
Visual Studio指向的行:
else if (item.FirstOrDefault().InspectionEquipmentTypes.Any())
例外的内部细节说:
There is already an open DataReader associated with this Command which must be closed first.
我的问题是提出错误的行不是尝试使用数据库/ datareader(据我所知)所以我不确定为什么会生成此异常。
编辑:
public static IEnumerable<IGrouping<string,Entities.Inspection>> GetUnscheduledBatchInspections(Entities.EntityModel context)
{
var results = context.Inspections.Where(w =>
w.InspectionBatchNo != null
&& w.IsCancelled == false
&& !w.CalendarItems.Any()
&& w.Duration.HasValue).GroupBy(g => g.InspectionBatchNo);
return results;
}
通话方式:
private void MapBatchInspectionsToViewModel(ref SchedulerViewModel viewModel)
{
var batchInspections = SchedulerManager.GetUnscheduledBatchInspections(this.Context);
foreach (var item in batchInspections)
{
var bigi = new BatchInspectionGridItem();
if (item.Any())
{
bigi.BatchInspectionNo = item.First().InspectionBatchNo;
if (item.FirstOrDefault().EquipmentTypeID != null)
{
bigi.EquipmentTypeName = item.FirstOrDefault().EquipmentType.Description;
}
else if (item.FirstOrDefault().InspectionEquipmentTypes.Any())
{
bigi.EquipmentTypeName = string.Join(" / ", item.FirstOrDefault().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(s => s.Duration);
}
viewModel.BatchInspectionGridViewModel.Add(bigi);
}
}
答案 0 :(得分:2)
以下是发生的事情:当您遍历batchInspections
时,数据库读取器正在从数据库中读取此集合。在循环中,您通过众多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。
必须要说的是,使用Entity Framework激活MARS几乎总是一个好主意,因为延迟加载有一种导致此异常的方法。
答案 1 :(得分:0)
当您以嵌套方式进行查询时会发生这种情况。
item.FirstOrDefault().InspectionEquipmentTypes.ToList().Any()
可能会奏效。我不确定。尝试简化嵌套查询。例如,不要进行如下查询:
items.Where(/*some condition*/).Any();
而不是
items.Any(/*some condition*/);
答案 2 :(得分:0)
如果你真的想要嵌套查询(我不建议这样做,我宁愿使用一些散列数据结构进行单独的查询和链接实体)并且你使用的是sql server,你实际上有另一种选择:activate火星。要激活它,只需添加连接字符串MultipleActiveResultSets = True。有关详细信息,请访问以下链接:https://msdn.microsoft.com/en-us/library/h32h3abf(v=vs.110).aspx