#c# #.net #linq #.net-6.0
#c# #.net #linq #.net-6.0
Вопрос:
Я ищу простой способ обновить/вставить/удалить элементы внутри одного списка (EF) с помощью данных из другого списка. В настоящее время я делаю что-то вроде этого:
public UpdateSomeList(Listlt;Foogt; foos, Listlt;Foogt; foosNew) { //remove missing foos.RemoveAll(x =gt; !foosNew.Select(xx =gt; xx.Id).Contains(x.Id)); //update existing var updatedCount = foosNew .Join(foos, @new =gt; @new.Id, old =gt; old.Id, (@new, old) =gt; { old.Value = @new.Value return old; } ) .Count(); //insert new var toAdd= foosNew .Where(x =gt; !foos.Select(xx =gt; xx.Id).Contains(x.Id)); foos.AddRange(toAdd); }
Есть ли более элегантный способ сделать это, или я просто должен сделать расширение для этого варианта использования из моего примера, и все?
Комментарии:
1. Необходимо ли обновлять существующий список, а не просто заменять его новым списком?
2. Вам нужно сохранить ссылку на старый список? Или создание нового-это вариант? Вам нужно обновить существующие элементы или возможна замена? На самом ли деле речь идет о слиянии данных в базе данных? И в вашем нынешнем подходе я настоятельно рекомендую сделать ` var newIds = foosNew. Выберите(xx =gt; xx.Id). ToHashSet();` вместо того, чтобы делать это в
Where
иRemoveAll
.3. @JohnathanBarclay В моем реальном коде у меня есть
PK Guid G_Id
иint Id
. Поэтому я не могу заменить их, потому что даже если идентификатор совпадает с идентификатором Guid, он будет другим, и при сохранении изменений новый объект будет сохранен в бд, а не обновлен4. Одна быстрая победа: замените
.Select(xx =gt; xx.Id).Contains(x.Id)
на.Any(xx =gt; xx.Id == x.Id)
5. Тогда @Kilas
In my real code
опубликует реальный код. Entity Framework имеет дело с таблицами, а не со списками. Если вы хотите обновить строки таблицы отдельными объектами, вам не нужно загружать данные, вам нужно только прикрепить новые объекты в измененном состоянии. Если вы хотите обновить только определенное поле, EF Core или любой ORM, вероятно, являются неправильным инструментом. В этом случае никакие объекты не задействованы, только ключи и значения. Зачем загружать объект, если вы действительно хотите его выполнитьupdate table1 set field1=@value when ID=@id
?
Ответ №1:
Я был бы склонен использовать что-то вроде этого:
public static void MergeWithlt;TItem, TKeygt;( this Listlt;TItemgt; destination, IEnumerablelt;TItemgt; newItems, Funclt;TItem, TKeygt; keySelector, Actionlt;TItem, TItemgt; update) { var itemsToAdd = newItems.ToDictionary(keySelector); destination.RemoveAll(x =gt; !itemsToAdd.ContainsKey(keySelector(x))); foreach (TItem oldItem in destination) { TKey key = keySelector(oldItem); TItem newItem = itemsToAdd[key]; itemsToAdd.Remove(key); update(oldItem, newItem); } destination.AddRange(itemsToAdd.Values); }
Использование:
foos.MergeWith(foosNew, x =gt; x.Id, (oldItem, newItem) =gt; { oldItem.Value = newItem.Value; });