Список обновлений из другого списка .NET6

#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; });