0

I transfer an entity object through MassTransit, change some properties and return it back. This of course involves serialization/deserialization in the background, done by MassTransit automatically using RabbitMQ.

When I try to attach or update the entity

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

it throws an expectation that the key is missing.

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

Just to mention that the primary key is called .MachineId which is not null, it has an int value.

The only way I found to update the object it to get it again from the context via .Find, and then use .CurrentValues.SetValues(transferedObject) like this:

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

Is there a better way how to attach and update the entity?

mileski
  • 158
  • 2
  • 11
  • 1
    Does this answer your question? https://stackoverflow.com/questions/50702865/entity-framework-attach-update-confusion-ef-core – Martin Staufcik May 01 '20 at 14:49
  • @MartinStaufcik that does indeed work and saves the changes, but the thing is the obejct has 4 collections on it, with many objects in the collection, and I think I need to traverse all of them and set the state to modified. I will try and see how it acts when not only a property on the object is changed, but also a property in an underlying object in the collections. Whereas Update does this without any need of traversing. That is why I asked if there is some other way. – mileski May 01 '20 at 15:10
  • What does `Machine` look like? If it's the root of an object graph any object in the graph can cause this exception. – Gert Arnold May 03 '20 at 18:19

1 Answers1

0

update method It puts all the properties in a query, even if no changes have been made to them.In the background , state of your object set modified. You can search all properties by reflection and only modify the ones that have been changed.