我有两个应用程序:一个应用程序是asp.net,另一个是在后台运行的Windows服务。
在后台运行的Windows服务正在数据库上执行某些任务(读取和更新),而用户可以通过asp.net app在数据库上执行其他操作。所以我很担心它,例如,在Windows服务中我收集一些满足条件的记录,然后我迭代它们,如:
IQueryable<EntityA> collection = context.EntitiesA.where(<condition>)
foreach (EntityA entity in collection)
{
// do some stuff
}
因此,如果用户修改稍后在循环迭代中使用的记录,那么该记录的值是什么?执行时检索的原始文件:
context.EntitiesA.where(<condition>)
或由用户修改并位于数据库中的新文件?
据我所知,在迭代过程中,EF会根据需求获取每个记录,我的意思是逐个,所以当读取下一个迭代的下一个记录时,此记录对应于从以下记录收集的记录:
context.EntitiesA.where(<condition>)
或位于数据库中的用户(用户刚刚修改过的那个)?
谢谢!
答案 0 :(得分:2)
这里有几个过程可以在EF中起作用。
那么这对你的情况意味着什么:
//nothing happens here you are just describing what will happen later to make the
// query execute here do a .ToArray or similar, to prevent people adding to the sql
// resulting from this use .AsEnumerable
IQueryable<EntityA> collection = context.EntitiesA.where(<condition>);
//when it first hits this foreach a
//SELECT {cols} FROM [YourTable] WHERE [YourCondition] will be performed
foreach (EntityA entity in collection)
{
//data here will be from the point in time the foreach started (eg if you have updated during the enumeration in the database you will have out of date data)
// do some stuff
}
答案 1 :(得分:0)
如果您真的担心会发生这种情况,那么请事先获取一份ID列表,然后分别使用新的DbContext
处理它们(或者说每批10次之后)。类似的东西:
IList<int> collection = context.EntitiesA.Where(...).Select(k => k.id).ToList();
foreach (int entityId in collection)
{
using (Context context = new Context())
{
TEntity entity = context.EntitiesA.Find(entityId);
// do some stuff
context.Submit();
}
}
答案 2 :(得分:0)
我认为你的问题的答案是'这取决于'。您描述的问题称为“不可重复读取”,可以通过设置正确的事务隔离级别来防止发生这种情况。但它带来了性能成本和潜在的死锁。
有关详细信息,请参阅this