JNY*_*ger 10 c# asp.net-mvc asynchronous entity-framework async-await
在ASP.NET MVC应用程序中,我收到了一个使用我的Entity Framework上下文的控制器方法的以下错误消息.
在先前的异步操作完成之前,在该上下文上开始第二操作.使用'await'确保在此上下文上调用另一个方法之前已完成任何异步操作.任何实例成员都不保证是线程安全的.
我知道你不能并行运行查询,所有东西似乎都在等待.如果我调试程序并逐步检查从EF返回的一些数据,那么它可以工作,可能是因为这会强制查询完成.
编辑 如果我在控制器方法的空检查中放置一个断点并检查shipmentDetail
异常的数据是不是抛出.
这是代码的一部分:
控制器方法:
[Route("{id:int}/Deliveries")]
public async Task<ActionResult> DeliveryInfo(int id)
{
var shipmentDetail = await db.ShipmentDetails.SingleOrDefaultAsync(s => s.Id == id);
if (shipmentDetail == null)
return HttpNotFound(string.Format("No shipment detail found with id {0}", id));
var model = await DeliveryInfoModel.CreateModel(db, shipmentDetail);
return View("DeliveryInfo", model);
}
Run Code Online (Sandbox Code Playgroud)
CreateModel方法:
public static async Task<DeliveryInfoModel> CreateModel(Context db, ShipmentDetail shipment)
{
DeliveryInfoModel model = new DeliveryInfoModel()
{
ShipmentInfo = shipment
};
//initialize processing dictionary
Dictionary<int, bool> boxesProcessed = new Dictionary<int, bool>();
List<DeliveryBoxStatus> statuses = new List<DeliveryBoxStatus>();
for (int i = 1; i <= shipment.BoxCount; i++ )
{
boxesProcessed.Add(i, false);
}
//work backwards through process
//check for dispositions from this shipment
if(shipment.Dispositions.Count > 0)
{
foreach (var d in shipment.Dispositions)
{
DeliveryBoxStatus status = new DeliveryBoxStatus()
{
BoxNumber = d.BoxNumber,
LastUpdated = d.Date,
Status = d.Type.GetDescription().ToUpper()
};
statuses.Add(status);
boxesProcessed[d.BoxNumber] = true;
}
}
//return if all boxes have been accounted for
if (boxesProcessed.Count(kv => kv.Value) == shipment.BoxCount)
{
model.BoxStatuses = statuses;
return model;
}
//check for deliveries
if(shipment.Job_Detail.Count > 0)
{
foreach (var j in shipment.Job_Detail.SelectMany(d => d.DeliveryInfos))
{
DeliveryBoxStatus status = new DeliveryBoxStatus()
{
BoxNumber = j.BoxNumber,
LastUpdated = j.Job_Detail.To_Client.GetValueOrDefault(),
Status = "DELIVERED"
};
statuses.Add(status);
boxesProcessed[j.BoxNumber] = true;
}
}
//check for items still in processing & where
foreach (int boxNum in boxesProcessed.Where(kv => !kv.Value).Select(kv => kv.Key))
{
//THIS LINE THROWS THE EXCEPTION
var processInfo = await db.Processes.Where(p => p.Jobs__.Equals(shipment.Job.Job__, StringComparison.InvariantCultureIgnoreCase) && p.Shipment == shipment.ShipmentNum && p.Box == boxNum)
.OrderByDescending(p => p.date)
.FirstOrDefaultAsync();
//process returned data
//...
}
model.BoxStatuses = statuses;
return model;
}
Run Code Online (Sandbox Code Playgroud)
我不完全确定这是因为在控制器中进行的查询,还是因为在循环中进行的查询未完成导致此行为.由于EF的懒惰,或者在这种情况下async/await如何工作,是否有什么我不了解实际查询/返回的时间?我有许多其他方法和控制器可以进行异步EF调用,并且之前没有遇到过这种情况.
编辑
我的上下文使用Ninject作为我的IoC容器注入我的控制器.这是NinjectWebCommon的RegisterServices方法中的配置:
kernel.Bind<Context>().ToSelf().InRequestScope();
Run Code Online (Sandbox Code Playgroud)
与Entity Framework一起使用异步时,请避免延迟加载.相反,要么首先加载您需要的数据,要么使用Include()
's'来确保您需要的数据随查询一起加载.
https://msdn.microsoft.com/en-gb/magazine/dn802603.aspx
异步支持的当前状态
...异步支持在版本6中添加到Entity Framework(在EntityFramework NuGet包中).但是,在异步工作时必须小心避免延迟加载,因为延迟加载总是同步执行....
(强调我的)
也:
归档时间: |
|
查看次数: |
3127 次 |
最近记录: |