EF数据库并发

时间:2013-06-20 20:13:10

标签: entity-framework concurrency dbcontext

我有两个应用程序:一个应用程序是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>)

或位于数据库中的用户(用户刚刚修改过的那个)?

谢谢!

3 个答案:

答案 0 :(得分:2)

这里有几个过程可以在EF中起作用。

  1. 查询仅在枚举时执行(有时称为查询实现),此时将执行整个查询
  2. 延迟加载仅影响上例中的导航属性。 where语句的结果集将一次性下拉。
  3. 那么这对你的情况意味着什么:

    //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