Entity framework 读取、递增和写回在多个用户中唯一的计数器(在EF 4中)

Entity framework 读取、递增和写回在多个用户中唯一的计数器(在EF 4中),entity-framework,concurrency,entity-framework-4,Entity Framework,Concurrency,Entity Framework 4,我有一个数据库表和一个相应的实体类(带有更改跟踪代理的POCO),其中有一个成员充当计数器: class MyEntity { public virtual int ID { get; set; } public virtual int Counter { get; set; } } 我的web应用程序中有一个函数,它必须通过ID获取该实体,读取计数器(然后用于分配给其他对象),增加它的值,然后将该实体写回数据库,如下所示: public int GetNewCounter(i

我有一个数据库表和一个相应的实体类(带有更改跟踪代理的POCO),其中有一个成员充当计数器:

class MyEntity
{
    public virtual int ID { get; set; }
    public virtual int Counter { get; set; }
}
我的web应用程序中有一个函数,它必须通过ID获取该实体,读取
计数器(然后用于分配给其他对象),增加它的值,然后将该实体写回数据库,如下所示:

public int GetNewCounter(int ID)
{
    int newCounter = 0;
    using (MyObjectContext ctx = new MyObjectContext())
    {
        MyEntity ent = ctx.MyEntities.Where(e => e.ID == ID).Single();
        ++ent.Counter;
        newCounter = ent.Counter;
        ctx.SaveChanges();
    }
    return newCounter;
}
// newCounter is now used for other stuff
两个或两个以上的用户可以同时执行此操作(使用相同ID的实体),我必须确保他们不读取并使用相同的计数器(因此,在第一个用户将递增的计数器存储回数据库之前,第二个用户不应能够获取计数器)

是否可以在读取实体之前“锁定”该实体,并在写回计数器更改后释放锁,然后在其他用户尝试读取同一实体时检查锁?这是一个合理的模式吗

使用实体框架(EF 4)实现此要求需要哪些选项

我对SQL Server和Entity Framework中的并发特性和思想非常不熟悉,如果能在这个特定问题上获得正确方向的帮助,我将不胜感激


提前谢谢你

我非常确定TransactionScope(使用事务)会锁定表,但您可能需要确保这就是您想要的(表锁)。您还可以查看ConcurrencyMode=“fixed”,尽管我不确定这是否能完全满足您的需求。

我尝试了一种解决方案,使用乐观并发并遵循该解决方案,将edmx模型文件中
MyEntity
中的
计数器属性的
并发模式设置为
固定

我很高兴看到是否有人可以对此进行审查,因为我不知道这是一个好的解决方案,或者是否有更简单的方法

public int GetNewCounter(int ID)
{
    int newCounter = 0;
    using (MyObjectContext ctx = new MyObjectContext())
    {
        MyEntity ent = ctx.MyEntities.Where(e => e.ID == ID).Single();
        int iRetries = 0;
        bool success = false;

        do
        {
            try
            {
                ++ent.Counter;
                newCounter = ent.Counter;
                ctx.SaveChanges();
                success = true;
            }
            catch (OptimisticConcurrencyException)
            {
                ctx.Refresh(RefreshMode.StoreWins, ent);
                ++iRetries;
                if (iRetries == 3) // give up after 3 retries
                    throw;
            }
        } while (!success);
    }
    return newCounter;
}

谢谢回复!明天我将更仔细地看一下这两个特性。在我看来,我不需要“表锁”,而是需要“行级”或单个“对象级”的锁,但我不知道是否存在这样的东西。