Я использую Entity Framework 6 Code First. Для использования моей базы данных мне нужна хранимая процедура. Всякий раз, когда создается база данных, эта хранимая процедура должна быть создана.EF6: где создавать хранимые процедуры?
Редактировать: причина хранимой процедуры написана в конце этого сообщения.
Из Stackoverflow Я знаю, как создать хранимую процедуру и как ее называть. Мой вопрос: где я его создаю?
Мой первый инстинкт был в DbContext.OnModelCreating. Эта функция вызывается всякий раз, когда создается модель. В этой функции вы скажете модельустроителю, как должна выглядеть модель.
Увы, в этой функции я еще не могу использовать DbContext. Существуют функции переопределения процедур Insert/Update/Delete, но мне нужна другая процедура.
Я считаю, чтобы добавить функцию в Seed функции DropCreateDataBaseIfModelChanges, но это будет препятствовать пользователям моей DbContext к семенной базе данных с помощью их собственных требуемых данных.
DbMigrations, похоже, разработан для переноса существующей базы данных на более новую. Не использовать, когда создается первая версия базы данных.
Итак, где создавать хранимые процедуры?
Редактировать. Причина, по которой мне нужна хранимая процедура, следующая:
Служба получает уведомления о том, что сегодня клиент потратил деньги на что-то. Мне нужно запомнить дневные итоги для каждого клиента.
- Если клиент не потратил ничего на дату, что если нет записи с (CUSTOMERID, дата) не существует, вставить запись с отработанным значением
- Это клиент уже провел что-то на datae, что если запись с (CUSTOMERID, дата) уже существует, добавьте потраченное значение к значению в записи
что-то вроде этого:
public void InsertOrAdd(int customerId, DateTime date, decimal value)
{
using (var dbContext = CreateContext())
{
var retrievedRecord = dbContext.Find(...)
if (retrievedRecord == null)
{
InsertRecord(customerId, date, value);
}
else
{
retrievedRecord.Value += value;
dbContext.SaveChanges();
}
}
}
Проблема в том, что после моего поиска у кого-то еще может быть вставлена запись. В этом случае я должен был добавить значение. Вместо этого будут две записи. Или, пока я обрабатываю существующую запись и добавляю ее, кто-то другой может обрабатывать одну и ту же существующую запись. Поэтому добавление значения должно быть сделано в базе данных с заявлением, как
update [CustomerSpends]
Set [SpentValue] = [SpentValue] + @Value
Where [CustomerId] = @CustomerId and [SpentDate] = @SpentDate
-редактировать Как * Иван Юрьев * уже упоминал выше, может быть решена с помощью транзакции. Однако у меня все еще возникнет проблема с добавлением расходов.
Если это будет процесс 3 шага, как говорит Иван, это было бы как:
- Fetch существующую запись
- Добавить spentValue в общей стоимости в отчете
- SaveChanges
Это имеет тот недостаток, что мне всегда нужны две круглые поездки в базу данных. Кроме того, я получаю последовательность расходов клиентов. Если какой-либо из них не работает, все нужно отменить. Даже при использовании транзакций возможны условия гонки
Высшее Transaction Isolation level (MSDN) считается совершенным.
READ COMMITTED Указывает, что операторы не могут считывать данные, которые были изменены, но не были совершены другими транзакциями. Это предотвращает грязные чтения. Данные могут быть изменены другими транзакциями между отдельными операциями в текущей транзакции, что приводит к невоспроизводимым считываниям или фантомным данным.
При использовании трехэтапной процедуры, описанной выше, я получаю запись X с общим затраченным значением 5,00 долларов США. Пока я добавляю 3 доллара к общей сумме, кто-то еще может получить запись X, потому что она еще не была изменена. Другой получает запись с общей суммой $ 5. После моего добавления общая стоимость стала $ 8. Я обновляю значение с помощью SaveChanges и продолжаю с другими записями. Через некоторое время я совершаю свои изменения. Другой процесс, у которого все еще есть запись с $ 5, должен добавить $ 2, заканчивая значением $ 7, тогда как конечный результат должен был быть $ 10
Использование транзакций не может помешать другим читать данные. Поэтому выборки - добавить значение - обновление должно быть сделано в один SQL заявление
Сущность-код кода сначала предназначен для перемещения процесса мысли от использования хранимых процедур/sql. Миграции баз данных фактически используются для представления вашей базы данных, как правило, при запуске новой базы данных, но ее можно использовать в обратном направлении. Это представление кода вместе с посещением используется для срывания базы данных и резервного копирования в соответствии с требованиями среды. Есть ли конкретная причина, по которой вам нужен SP? –
Что-то вроде: помните затраты на клиента в день. Если клиент уже внес расходы в этот день, добавьте новое значение, иначе создайте стоимость на сегодняшний день и инициализируйте его значением. Если я найду и обнаруживаю, что его нет, я мог бы добавить, но тем временем кто-то другой мог бы сделать то же самое. Поэтому это должно быть в одном выражении SQL. вероятно, что-то вроде слияния –
Почему вы не используете транзакцию, чтобы кто-то другой не вносил запись в базу данных? –