Entity Framework - Сокращение количества обращений к базе данных - PullRequest
0 голосов
/ 16 августа 2011

Я пишу приложение, используя WPF, Entity Framework и SQLServer, все это очень удобно.Я смотрел, какие звонки поступают в базу данных с помощью sql profiler, и нашел немало ненужных звонков.Первый был решен довольно легко, но я включил его для всех, кто читает эту ветку в будущем.Предполагая, что у меня есть структура таблицы с 3-мя таблицами, подобными этой Invoice-> InvoiceDetail-> Product

1) Когда я загружаю объект Invoice, он затем выполняет отдельный оператор для извлечения каждого элемента InvoiceDetail.Это легко решается с помощью оператора Include, например,

context.Invoices.Include("InvoiceDetails").Where(i => i.Something == somethingelse);

2) Когда я удаляю счет-фактуру, база данных имеет каскадное удаление, которое автоматически удаляет все InvoiceDetails.Однако EF по-прежнему настаивает на вызове удаления для каждого из объектов InvoiceDetail, которые он имеет в памяти.Если в счете 100 позиций, то он выполнит 101 инструкцию вместо 1. Это плохо.

3) В дополнение к дополнительным инструкциям, выполненным в пункте 2, предполагается, что каждый объект InvoiceDetail указывает на продукт иЯ вызвал загрузку продуктов в память (это произошло бы, если бы я показал счет до того, как его удалил), а затем EF выполняет бесполезный оператор обновления для каждого продукта !!!!Фактически, это заявление об обновлении более чем бесполезно, потому что, если кто-то еще что-то изменил в продукте, то этот код вернет данные обратно !!Если я регистрирую изменения, мы получаем бесполезные записи в журнале.Я подозреваю, что это происходит потому, что в Product была бы коллекция InvoiceDetails, в которой были удалены некоторые элементы, но сам продукт не изменился, так почему обновление?

Спасибо за чтение Cheers, Майкл

Ответы [ 3 ]

2 голосов
/ 16 августа 2011
  1. Начальное поведение было так называемым отложенной загрузкой.Вы заменили его на готовую загрузку, которая является точным решением этой проблемы.
  2. Для структуры сущностей это единственно правильное поведение, потому что EF не поддерживает пакетные модификации.Каждая запись должна быть удалена со своим выпиской и туда-обратно в базу данных.После того, как вы загрузите объекты в память, вы просто должны удалить их один за другим, в противном случае вы получите исключение до того, как будет выполнен любой вызов базы данных (= каскадное удаление базы данных вам не поможет).Единственный обходной путь - настраиваемая хранимая процедура для удаления и удаления текущего контекста после запуска хранимой процедуры, поскольку ее внутреннее состояние не будет соответствовать базе данных.
  3. Это интересно.Это потребовало бы немного больше исследования, но это может быть просто ошибка проектирования / ошибки в EF, и вы, скорее всего, не избежите этого (если вы не используете хранимую процедуру, как описано в 2.).Если вы хотите избежать перезаписи изменений в Product, вы должны задействовать оптимистичный параллелизм .В этом случае ваши изменения не будут перезаписаны, но ваше удаление не будет выполнено с OptimisticConcurrencyException.Я проверю это поведение позже и сообщу, смогу ли я воспроизвести его и найду обходной путь.
0 голосов
/ 17 августа 2011

Я использовал это как решение, позволяющее SQL Server обрабатывать каскадные удаления без нажатия EF.

  Public Sub DeleteCheckedOutByUser(ByVal username As String)
    Dim cmd As String = String.Format("delete  Maintenance.CheckoutManager where CheckOutTo = '{0}'", username)
    _context.ExecuteStoreCommand(cmd)
  End Sub

Извините, это в VB, это то, что использует мой текущий клиент. Если у вас возникнут проблемы с переводом того, что я говорю, просто дайте мне знать.

0 голосов
/ 16 августа 2011

Чтобы удалить каскадные удаления (и, вероятно, для удаления используйте SQL Server), см. Подход здесь: http://geekswithblogs.net/danemorgridge/archive/2010/12/17/ef4-cpt5-code-first-remove-cascading-deletes.aspx

...