Лучший способ обновить коллекцию данных SQL - PullRequest
0 голосов
/ 20 января 2019

Я пишу фрагмент кода .net / entity Framework, который должен обновить / удалить группу строк MS SQL с последними данными, переданными из пользовательского интерфейса. Скажем, у таблицы изначально есть 20 строк, а последняя коллекция содержит 15 записей. Из 15 9 имеют изменения, а 6 остаются прежними. Таким образом, 9 строк будут обновлены, а 5 строк, которые не входят в последнюю коллекцию, будут удалены из таблицы. Итак, мой вопрос, каков наилучший способ сделать это: если я переберу все 20 строк и попытаюсь найти каждый из них, это будет O (mn). Удаление всех строк таблицы и их повторная вставка могут быть быстрее, но я не уверен. Вся помощь оценена!

1 Ответ

0 голосов
/ 23 января 2019

Итак, у вас есть элемент пользовательского интерфейса, заполненный элементами некоторого класса.У вас также есть база данных с таблицей, заполненной элементами того же класса.

IEnumerable<MyClass> userInterfaceElements = ...
IQueryable<MyClass> databaseElements = ...

Примечание: запрос еще не выполнен!

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

  • Элементы пользовательского интерфейса, которых еще нет в базе данных, будут добавлены
  • Элементы базы данных, которых нет в пользовательском интерфейсе, необходимо удалить
  • Элементы пользовательского интерфейсакоторые также должны быть обновлены в базе данных.

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

var itemsToAdd = userInterfaceElements.Where(row => row.Id == 0);
var itemsToUpdate = userInterfaceElements.Where(row => row.Id != 0);

var idsItemsToKeep = itemsToUpdate.Select(row => row.Id);
var itemsToRemove = databaseElements.Where(row => !idsItemsToKeep.Contains(row.Id))

Последнее: удалите все элементы с идентификатором, которого больше нет в ваших элементах пользовательского интерфейса.

Примечание: мы все еще не выполнили ни одного запроса!

Добавление элементов в вашу базу данных изменит элемент databaseElements, поэтому, прежде чем вносить какие-либо изменения, вам необходимо материализовать элементы

var addList = itemsToAdd.ToList();
var updateList = itemsToUpdate.ToList();
var removeList = itemsToRemove.ToList();

. Теперь вы запросили базу данных ровно один раз: вы выбрали все элементы для удаления.,Вы не можете заказать платформу сущностей для удаления элементов без предварительной выборки.

dbContext.MyClasses.RemoveRange(removeList);
dbContext.MyClasses.AddRange(addList);

Чтобы обновить в платформе сущностей, правильным методом будет выборка данных, а затем изменение свойств.

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

Правильный путь:

foreach(var itemToUpdate in updateList)
{
     var fetchedItem = dbContext.MyClasses.Find(itemToUpdate.Id);
     // TODO: update changed properties of the fetchedItem with values from itemToUpdate
}

Опасный метод:

foreach(var itemToUpdate in updateList)
{
    dbContext.Entry(itemToUpdate).State = entityState.Modified;
}

Наконец:

dbContext.SaveChanges();

Улучшенный метод удаления

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

Когда ваш код смотрит на первичный ключ, он будет думать, что он находится в базе данных, но его больше нет.Что делать с этим элементом?Добавить еще раз?Действовать так, как если бы пользователь также хотел, чтобы он был удален?

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

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

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

Приятная вещь в устаревшем состоит в том, что если кто-то объявил элемент устаревшим случайно, у него все еще есть время для его ремонта.

...