我有两个应用程序:一个是asp.net,另一个是在后台运行的windows服务。
后台运行的windows服务对数据库执行一些任务(读取和更新),而用户可以通过asp.net应用程序对数据库执行其他操作。例如,在windows服务中,我收集一些满足条件的记录,然后遍历它们,例如:
IQueryable<EntityA> collection = context.EntitiesA.where(<condition>)
foreach (EntityA entity in collection)
{
// do some stuff
}因此,如果用户修改了稍后在循环迭代中使用的记录,那么该记录的EF将被考虑到什么值?执行时检索到的原件:
context.EntitiesA.where(<condition>)还是由用户修改并位于数据库中的新文件?
据我所知,在迭代期间,EF是按需获取每条记录的,我的意思是,逐条记录,所以当读取下一次迭代的下一条记录时,此记录对应于从以下位置收集的记录:
context.EntitiesA.where(<condition>)还是位于数据库中(用户刚刚修改的那个)?
谢谢!
发布于 2013-06-21 04:35:18
有几个过程将在这里发挥作用,在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
}发布于 2013-06-21 04:36:04
如果您真的担心这种情况会发生,那么预先获取一个id列表,并为每个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();
}
}发布于 2013-06-21 04:46:53
我想你的问题的答案是‘视情况而定’。您所描述的问题称为“不可重复读取”,可以通过设置适当的事务隔离级别来防止发生。但它也带来了性能上的代价和潜在的死锁。
有关更多详细信息,请阅读this
https://stackoverflow.com/questions/17222919
复制相似问题