2016-05-24 3 views
0

Я использую 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 заявление

+0

Сущность-код кода сначала предназначен для перемещения процесса мысли от использования хранимых процедур/sql. Миграции баз данных фактически используются для представления вашей базы данных, как правило, при запуске новой базы данных, но ее можно использовать в обратном направлении. Это представление кода вместе с посещением используется для срывания базы данных и резервного копирования в соответствии с требованиями среды. Есть ли конкретная причина, по которой вам нужен SP? –

+0

Что-то вроде: помните затраты на клиента в день. Если клиент уже внес расходы в этот день, добавьте новое значение, иначе создайте стоимость на сегодняшний день и инициализируйте его значением. Если я найду и обнаруживаю, что его нет, я мог бы добавить, но тем временем кто-то другой мог бы сделать то же самое. Поэтому это должно быть в одном выражении SQL. вероятно, что-то вроде слияния –

+0

Почему вы не используете транзакцию, чтобы кто-то другой не вносил запись в базу данных? –

ответ

1

Лучший способ управления путем создания пустой миграции и добавить хранимую процедуру в Up метод и удалить эту хранимую процедуру в Нисходящий метод ,

Это будет работать как.

1) Добавить пустую миграцию, выполнив команду пакета сене консоли

add-migration 'SomeName' -IgnoreChanges 

Это создаст файл миграции

2) Теперь Добавьте хранимую процедуру вверх и удалить хранимую процедуру в Даун

public partial class SomeName: DbMigration 
    { 
     public override void Up() 
     { 
      Sql(@"Add Command For StoredProcedure"); 

     } 

     public override void Down() 
     { 
      Sql(@"Drop Command for Stored Procedure") 
     } 
    } 

Добавление метода Drop in Down не менее важно.

1

Нигде. Я обнаружил, что первые миграции кода чрезвычайно ограничены, и что только люди, которые не имеют глубокого понимания концепций и возможностей SQL-сервера, будут чувствовать себя комфортно.

Путь я пошел в:

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

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

Рассказывая полную правду - я никогда не находил код первым даже эффективным подходом. Это слишком склонно к ошибкам. Единственное, что хуже, это db сначала с инструментами EF - главным образом потому, что дизайнер edmx настолько же прогнив, насколько и получается, полностью не в состоянии справиться с обновлениями. Тем не менее сторонние редакторы доступны, и они работают.

+0

Я в последнее время думал совершенно так же ... какие инструменты сторонних производителей вы бы порекомендовали? – Jcl

+0

У Devart есть альтернативный редактор, который прыжков и границ впереди незавершенного редактора MS. – TomTom

Смежные вопросы