EF4 обновляет значение для всех строк в таблице, не делая выбор - PullRequest
4 голосов
/ 19 февраля 2011

Мне нужно сбросить логическое поле в конкретной таблице перед запуском обновления.Таблица может содержать около 1 миллиона записей, и я предпочел бы не делать выбор перед обновлением, так как это занимает слишком много времени.

В основном, что мне нужно в коде, это произвести следующее вTSQL

update tablename 
set flag = false 
where flag = true

У меня есть кое-что, близкое к тому, что мне нужно здесь http://www.aneyfamily.com/terryandann/post/2008/04/Batch-Updates-and-Deletes-with-LINQ-to-SQL.aspx, но я еще не реализовал его, но мне было интересно, есть ли более стандартный способ.

следуйте ограничениям, которые у нас есть для этого проекта, мы не можем использовать SPROC или напрямую писать TSQL в параметре ExecuteStoreCommand для контекста, который, я полагаю, вы можете сделать.

Я знаю, что то, что мне нужно сделать, может небыть непосредственно поддержанным в EF4, и нам, возможно, придется искать SPROC для работы [при полном отсутствии какого-либо другого пути], но мне просто нужно сначала полностью изучить все возможности.В идеальном мире EF вызов выше для обновления флага был бы возможен, или в качестве альтернативы было бы возможно получить объект с идентификатором и логическим флагом только минус ассоциированные объекты и выполнить цикл по объекту и установить флаг и выполнить одинВызов SaveChanges, но, возможно, это не совсем так.

Любые идеи,

Заранее спасибо.Лиам

Ответы [ 3 ]

4 голосов
/ 19 февраля 2011

Я хотел бы обратиться к заинтересованному лицу, которое ввело ограничения на неиспользование SQL или SProc напрямую, и представил бы ему следующие факты:

  • Обновления в ORM (например, структура сущностей) работают следующим образом: вы загружаете объект, который выполняетеМодификация сохраняет объект.Это единственный верный способ.
  • Очевидно, что в вашем случае это будет означать загрузку 1M сущностей и выполнение 1M обновлений отдельно (EF не имеет пакетной обработки команд - каждая команда запускается в отдельном цикле передачи в БД) - обычно абсолютно бесполезное решение.
  • Приведенный вами пример выглядит очень интересным, но он предназначен для Linq-To-Sql.Не для Entity Framework.Если вы не реализуете его, вы не можете быть уверены, что он будет работать для EF, потому что инфраструктура в EF намного сложнее.Таким образом, вы можете потратить несколько человеко-дней, выполняя это без какого-либо результата - это должно быть одобрено заинтересованными сторонами.
  • Решение с SProc или прямым SQL займет у вас несколько минут, и оно будет просто работать.
  • В обоих решениях вам придется иметь дело с другой проблемой.Если у вас уже есть материализованные сущности, и вы запустите такую ​​команду (через упомянутое расширение или через SQL), эти изменения не будут отражены в уже загруженных сущностях - вам придется их повторять и устанавливать флаг.
  • Оба сценариянарушить единицу работы, поскольку некоторые изменения данных выполняются до завершения единицы работы.

Все дело в использовании правильного инструмента для правильного требования.

Btw.можно не загружать загруженные таблицы.Речь идет о запросе, который вы выполняете.Не используйте Включить и не открывайте свойства навигации (в случае отложенной загрузки), и вы не будете загружать отношения.

Можно выбрать только Id (через проекцию), создать фиктивную сущность (установить только id ии указывать на true) и выполнять только обновления флага, но он все равно будет выполнять до 1M обновлений.

using(var myContext = new MyContext(connectionString))
{
  var query = from o in myContext.MyEntities
              where o.Flag == false
              select o.Id;
  foreach (var id in query)
  {
    var entity = new MyEntity
      {
        Id = id,
        Flag = true
      };
    myContext.Attach(entity);
    myContext.ObjectStateManager.GetObjectStateEntry(entity).SetModifiedProperty("Flag");
  }

  myContext.SaveChanges();
}

Более того, он будет работать только в пустом контексте объекта (или, по крайней мере, никакая сущность из обновленной таблицы не может быть присоединена к контексту).Таким образом, в некоторых сценариях, выполняющих это перед другими обновлениями, потребуется два ObjectContext экземпляра = совместное использование вручную DbConnection или два подключения к базе данных, а в случае транзакций = распределенная транзакция и другое снижение производительности.

0 голосов
/ 19 февраля 2011
ObjectContext.ExecuteStoreCommand ( _
    commandText As String, _
    ParamArray parameters As Object() _
    ) As Integer

http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.executestorecommand.aspx

Редактировать
Извините, не прочитал пост полностью.

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

Создайте новую модель EF и добавьте только одну Таблицу, для которой необходимо выполнить обновление. Таким образом, все соединения не происходят. Это значительно ускорит вашу обработку.

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