Сценарии «следующего числа» с использованием Entity Framework - PullRequest
2 голосов
/ 05 февраля 2011

Я играл с Entity Framework и до сих пор мне очень нравится его использовать. Но все, что я до сих пор делал, предполагает оптимистическую блокировку, которая в большинстве случаев хорошо работает для меня. Однако у меня есть следующий сценарий:

  1. Таблица SQL Server только с одной строкой, которая содержит данные для всего приложения
  2. Строка содержит столбец с именем «NextAvailableNumber»
  3. Приложение должно прочитать число, увеличить его на 1 и обновить

Вышеуказанное должно гарантировать, что любой конкурирующий процесс должен дождаться получения номера до завершения первой транзакции. Ранее мы делали это с помощью блокировок таблицы (поскольку есть только одна строка), но я хотел бы знать, как это сделать с помощью LINQ to Entities?

Спасибо

Джим К.

Ответы [ 3 ]

1 голос
/ 06 февраля 2011

Я думаю, вам нужно реализовать это в хранимой процедуре, потому что вы используете явную блокировку строк (или блокировку таблиц, как вы упоминали).Тогда вы будете вызывать эту процедуру из EF.Я не думаю, что это можно сделать из кода приложения, если вы не используете сериализуемую транзакцию каждый раз, когда работаете со своей специальной таблицей.Это может оказать огромное негативное влияние на производительность приложения.

На самом деле мы делаем нечто подобное, но наша таблица содержит множество строк для разных последовательностей, поэтому я использую хранимую процедуру с блокировкой строк и обновлением.Сначала мы хотели вызвать эту процедуру в методе вставки нашего репозитория, но после этого я переместил ее в базу данных и вызвал свою процедуру после триггера вставки.Причина этого заключалась в том, чтобы отложить блокировку строки на время реальной вставки в базу данных, а не на время маркировки сущности для вставки в контексте EF (сама вставка и вызов процедуры должны быть в одной транзакции в нашем случае).Я изменил свою модель EF так, чтобы в связанном свойстве StoreGeneratedPattern было установлено значение computed.После каждой вставки EF будет запрашивать DB для получения назначенного порядкового номера.Единственным недостатком является то, что EF также будет запрашивать БД после каждого обновления этих объектов, но в нашем случае это уже происходит из-за отметки времени.Это все еще находится в стадии тестирования и оценки, поэтому я все еще могу изменить свое мнение и переопределить его.

1 голос
/ 01 июня 2011

Существует еще одно решение, которое мы используем, и вы можете использовать его, чтобы избежать использования Процедур Магазина, особенно если вы используете EF Code First, как мы.Code First не поддерживает использование процедур хранения.

Решение использует метод EF SqlQuery в рамках транзакции, вы должны написать запрос, который сначала выполняет обновление счетчика следующего числа,затем выберите его.Код будет:

string query = "UPDATE Registre_Counter SET Counter = Counter + 1 WHERE CounterName = @p0 AND Year = @p1;";
query += "select * from Registre_Counter Where CounterName = @p0 AND Year = @p1";

GenericCounter GenericCounter = CoreDBContext.Instance().GenericCounter.SqlQuery(query, new Object[] { _counterName, _year }).SingleOrDefault(); //Updates the counter and return de NextNumber to Use

Обновление заблокирует счетчик и предотвратит чтение из других транзакций, пока транзакция не будет прервана или зафиксирована.

0 голосов
/ 05 февраля 2011

Поскольку платформа Entity использует оптимистическую блокировку, она выдаст исключение при изменении следующего числа вторым процессом.Самый примитивный способ противостоять этой ситуации - поймать исключение и повторить изменение, пока оно не будет успешным.[к этому можно добавить тайм-аут, чтобы гарантировать выполнение кода в худшем случае]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...