Как вставить в таблицу соединений с Entity Framework 4.1, когда отслеживание изменений отключено? - PullRequest
2 голосов
/ 23 декабря 2011

Справочная информация: Я работаю над проектом, в который импортирую группу данных из файла CSV в базу данных с использованием .NET Entity Framework (v4.1).Во время импорта я ожидаю увидеть много «ошибок» (т. Е. Ошибок поиска), возможно, несколько в каждой строке, и они должны быть позже разрешены администратором посредством ручного процесса.Многие ошибки одинаковы для каждой строки (т. Е. Один и тот же столбец, одно и то же значение данных и один и тот же код ошибки, но разные строки), поэтому, чтобы администратору было легче их разрешать, я их объединяю.Другими словами, при вставке данных строки, если я сталкиваюсь с ошибкой, которая была замечена ранее в другой строке, я связываю новую строку с этой ошибкой вместо вставки новой.Я использую хеш-таблицу для быстрого поиска.

Моя модель выглядит следующим образом:

  • Каждый файл представлен ImportFile объектом
  • Каждый ImportFile имеет коллекцию ImportErrors (один ко многим)
  • Каждый ImportFile также имеет коллекцию DataRows (один ко многим)
  • Между DataRows и ImportErrors существует отношение «многие ко многим», так что у каждого есть коллекция другого.

Моя загадка: У меня работает коди вставка всех этих данных в базу данных должным образом, но когда размер файла импорта начинает превышать, скажем, несколько сотен строк, производительность ужасна.Я уверен, что это происходит из-за отслеживания изменений, которое осуществляется Entity Framework за кулисами.Я бы хотел отключить отслеживание изменений, чтобы повысить производительность, но если я это сделаю, я не вижу способа заставить Entity Framework вставлять записи соединения между DataRows и ImportErrors.Как я уверен, вы знаете, Entity Framework не генерирует сущность для представления объединения;вместо этого он проверяет, добавили ли вы элементы в соответствующие коллекции на соединенных объектах.

Итак, кто-нибудь знает способ обойти это?Есть ли способ явно указать платформе сущностей на вставку записи соединения?Или есть лучший способ сделать это?

В настоящее время я использую один DbContext для всего импорта.Я создаю все объекты, добавляя их в контекст по ходу работы, а затем в конце делаю один SaveChanges ().

Другие вещи, которые я пробовал:

  • Более частый вызов SaveChanges () (по одному разу в строке) - это делало вещи еще медленнее
  • Попытка использовать новый DbContext для каждого DataRow - в этом случае структура сущности жаловалась, что «связьмежду этими двумя объектами нельзя определить, потому что они прикреплены к разным объектам ObjectContext. "Ошибка не говорит, какие конкретные объекты она пыталась связать в то время.Я пробовал это несколькими способами, и я не могу сделать EF счастливым, независимо от того, что я делаю с этим подходом.

Другие подходы, которые я рассматриваю, но еще не пробовали:

  • Создание способа разбить файл импорта на маленькие 100-строчные чанки, а затем обрабатывать каждый чанк как отдельный файл (для каждого чанка мне нужно было бы перезагрузить все мои поисковые данныеи ошибки предыдущих блоков, так что все они в одном контексте)
  • Создание хранимых процедур для облегчения вставок вместо них (во-первых, это противоречит принципу использования EF, но я будусделайте это, если нет другого пути)

Большое спасибо заранее за ваши идеи.-Брайан

Ответы [ 2 ]

2 голосов
/ 23 декабря 2011

Я уверен, что это происходит из-за отслеживания изменений, которое выполняется Entity Framework за кулисами.

Я не уверен.Это может быть правдой, если отслеживание изменений основано на снимках, то есть вы используете POCO (вы используете EF 4.1) и не работаете с прокси отслеживания изменений.Но отслеживание изменений с помощью прокси-серверов на самом деле происходит очень быстро (до 50 раз быстрее, чем отслеживание изменений на основе моментальных снимков, исходя из моего собственного опыта с аналогичной проблемой).

Но для включения прокси-серверов отслеживания изменений требуется строгое требование: все Свойства вашей модели должны быть virtual, не только свойства навигации, но и скалярные свойства.В этом случае EF по умолчанию включит прокси отслеживания изменений.Вы можете отключить его в других ситуациях, когда они вам не нужны или не нужны:

context.Configuration.ProxyCreationEnabled = false;

Наличие всех свойств virtual также включит отложенную загрузку по умолчанию.Если вы не хотите этого, вы можете отключить его:

context.Configuration.LazyLoadingEnabled = false;

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

Другое решение, которое вы можете проверить, - отключить автоматическое отслеживание изменений:

context.Configuration.AutoDetectChangesEnabled = false;

Это также может улучшить производительность.Но вы должны быть осторожны, чтобы вызывать context.ChangeTracker.DetectChanges() вручную в соответствующих точках, чтобы не допустить ошибок в вашем коде.

Другие параметры, кроме хранимых процедур (как вы сказали) или использование прямого SQL.EF не предлагает другого способа вставки данных в таблицу соединений, кроме использования механизма отслеживания изменений.

0 голосов
/ 24 декабря 2011

Я нашел способ справиться с проблемой: я создал явную сущность для записи соединения в моей модели. Итак, теперь существует объект DataRowImportError , который имеет отношение один ко многим как с DataRow, так и с ImportError, в то время как DataRow и ImportError больше не имеют прямой связи между ними. Это позволяет мне вставлять (или удалять) записи о соединении напрямую, что, в свою очередь, позволяет отключить отслеживание изменений во время импорта и значительно повысить производительность. Единственным недостатком является то, что модель не настолько «дружелюбна» для работы, но, эй, иногда это стоит бизнеса.

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