Чтение, увеличение и запись счетчика, уникального для нескольких пользователей (в EF 4) - PullRequest
2 голосов
/ 09 августа 2010

У меня есть таблица базы данных и соответствующий класс сущности (POCO с прокси-сервером отслеживания изменений) с членом, который действует как счетчик:

class MyEntity
{
    public virtual int ID { get; set; }
    public virtual int Counter { get; set; }
}

В моем веб-приложении есть функция, которая должна извлечь этосущность по идентификатору, прочитайте Counter (который затем используется для назначения другим объектам), увеличьте его и запишите сущность обратно в базу данных, например, так:

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

Два или более пользователей могутсделать это одновременно (с сущностью с одинаковым идентификатором), и я должен убедиться, что они не читают и не используют один и тот же счетчик (поэтому второй пользователь не сможет получить счетчик до того, как первый пользователь получитсохранил увеличенный счетчик обратно в базу данных).

Можно ли "заблокировать" сущность до того, как она будет прочитана, и снять блокировку после обратной записи изменения счетчика, а затем проверить наличие блокировки, когда другой пользовательпытается прочитать ту же сущность?Это разумный шаблон вообще?

Какие варианты у меня есть для реализации этого требования с Entity Framework (EF 4)?

Я очень незнаком с функциями и идеями параллелизма в SQL Serverи Entity Framework, и мы будем рады получить помощь в правильном направлении с этой конкретной проблемой.

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 09 августа 2010

Я почти уверен, что TransactionScope (используя транзакцию) заблокирует таблицу, но вы можете быть уверены, что именно этого вы хотите (блокировка таблицы). Вы также можете посмотреть ConcurrencyMode = "fixed", хотя я не уверен, что это даст вам именно то, что вы ищете.

0 голосов
/ 10 августа 2010

Я пробовал решение, используя оптимистичный параллелизм и следуя ответу ThatSteveGuy, установив ConcurrencyMode в fixed для свойства Counter в MyEntity в файле модели edmx.

Я был бы рад узнать, может ли кто-нибудь рассмотреть это, поскольку я не знаю, является ли это хорошим решением или есть более простой способ.

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...