Я передаю сущность-объект через MassTransit, меняю некоторые свойства и возвращаю обратно. Это, конечно, включает сериализацию/десериализацию в фоновом режиме, выполняемую MassTransit автоматически с помощью RabbitMQ.

Когда я пытаюсь прикрепить или обновить сущность

_machinesContext.Machines.Update((Machine)machine);

Это вызывает ожидание, что ключ отсутствует.

ex = {"Value cannot be null. (Parameter 'key')"}

at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)\r\n   at System.Collections.Generic.Dictionary`2.FindEntry(TKey key)\r\n   at System.Collections.Generic.Dictionary`2.TryGetValue(TKey key, TValue& value)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityReferenceMap.TryGet(Object entity, IEntityType entityType, InternalEntityEntry& entry, Boolean throwOnNonUniqueness)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.TryGetEntry(Object entity, IEntityType entityType, Boolean throwOnTypeMismatch)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.InitialFixup(InternalEntityEntry entry, Boolean fromQuery)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.StateChanged(InternalEntityEntry entry, EntityState oldState, Boolean fromQuery)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryNotifier.StateChanged(InternalEntityEntry entry, EntityState oldState, Boolean fromQuery)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.FireStateChanged(EntityState oldState)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)\r\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)\r\n   at Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)\r\n   at Microsoft.EntityFrameworkCore.DbContext.SetEntityState[TEntity](TEntity entity, EntityState entityState)\r\n   at Microsoft.EntityFrameworkCore.DbContext.Update[TEntity](TEntity entity)\r\n   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Update(TEntity entity)\r\n

Просто упомянем, что первичный ключ называется .MachineId, который не равен нулю, он имеет значение int.

Единственный способ обновить объект, который я нашел, это снова получить его из контекста через .Find, а затем использовать .CurrentValues.SetValues(transferedObject) следующим образом:

var existingMachine = await _machinesContext.Machines.FindAsync(machine.MachineId);
_machinesContext.Entry(existingMachine).CurrentValues.SetValues((Machine)machine);
await _machinesContext.SaveChangesAsync();

Есть ли лучший способ прикрепить и обновить сущность?

0
mileski 1 Май 2020 в 17:35
1
Отвечает ли это на ваш вопрос? stackoverflow.com/questions/50702865 /…
 – 
Martin Staufcik
1 Май 2020 в 17:49
Это действительно работает и сохраняет изменения, но дело в том, что объект имеет 4 коллекции со многими объектами в коллекции, и я думаю, что мне нужно обойти их все и установить измененное состояние. Я попытаюсь посмотреть, как это действует, когда изменяется не только свойство объекта, но и свойство базового объекта в коллекциях. В то время как Update делает это без необходимости обхода. Поэтому я и спросил, есть ли другой способ.
 – 
mileski
1 Май 2020 в 18:10
Как выглядит Machine? Если это корень графа объектов, любой объект в графе может вызвать это исключение.
 – 
Gert Arnold
3 Май 2020 в 21:19

1 ответ

Метод обновления Он помещает все свойства в запрос, даже если в них не было внесено никаких изменений. В фоновом режиме состояние вашего набора объектов изменено. Вы можете искать все свойства по отражению и изменять только те, которые были изменены.

0
farshid jahanmanesh 1 Май 2020 в 18:36