我有一个使用ASP.NET MVC(C#),实体框架和Oracle数据库编写的Web应用程序。在其中一个控制器中,我具有与以下类似的代码(向下拖动以仅显示我认为对该问题必要的内容):
using (var context = CreateContext())
{
//Other code ...
var workItem = //Get work item from context
var nextReviewers =
await context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id)
.Where(r => r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.ToArrayAsync();
if (nextReviewers.Count() > 0)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewers.First().Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
//Other Code
await context.SaveChangesAsync();
}
基于上述代码,我从不期望状态或StatusDetails的值会有所不同,但是在生产环境中,两个请求相距约3-4毫秒,现在, 莫名其妙地,我在数据库中有以下值:Status =“ B”; StatusDetails =“ A”。
我想念什么吗?是否存在基于EntityFramework(针对Oracle 11g)在ASP.NET中的行为的逻辑解释?
答案 0 :(得分:1)
基于上面的代码,鉴于更新的workItem实体是在数据库上下文的范围内加载的,并且两个值是字符串,我必须以99.5%的把握确定此代码对您所看到的行为。 (尽管我肯定会看这个项目,以查看是否被证明是错误的:)我将密切关注在与对服务的调用有关的情况下使用Status或StatusDetails的所有地方。我怀疑其他一些代码意外地更改了另一个,并调用了SaveChanges。
我可以建议进行一个小的优化
var nextReviewer = context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id
&& r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.Select(r => new { r.Position }) // Add any other details you may need from reviewer and other related entities.
.FirstOrDefault();
if (nextReviewer != null)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewer.Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
通过使用.Select()
,您可以优化查询以仅返回所需表中的列,从而使对数据库的调用更快。除非期望查询在时间上相对繁重(例如,> 500ms),否则我还要避免异步操作。目的是使服务器在处理更大的操作时响应更快。在所有内容上使用它会使所有操作的速度都比必要的慢。对返回的数据进行优化之后,如果仍然需要一些时间来解决问题,那么可以考虑使用异步。