Reputation: 9437
I have an EF7 DbContext
with disabled change tracking because I want to mark all changes explicitly:
var entry = context.Entry(changedEntity);
entry.Property(propertyName).IsModified = true;
This works exactly as I want it to.
However, this does not work when a reference (navigation property) has been updated.
For example, let's say my entity has two properties - ParentId
and Parent
where ParentId
is a foreign key and Parent
is the reference to the parent entity.
Calling
entry.Property("Parent").IsModified = true;
does not work and throws ModelItemNotFoundException
because Parent
is not a property of the entity in terms of EF (it is a navigation instead).
In EF6, this could be done as follows:
var reference = context.Entry(changedEntity).Reference("Parent");
reference.CurrentValue = reference.CurrentValue;
IN EF7, there is no such function. I can get to the INavigation
object with
entry.Metadata.GetNavigation("Parent")
but cannot see any way to mark it as modified.
So, how should I do it?
Note:
I know that setting ParentId
would work, but this is not suitable for me because the referenced entity does not have ID yet as it has just been created and will get its ID from database when saved. Thus, I need to set it through the reference Parent
.
Edit:
The note above was true for EF6 but is no longer valid for EF7 which I was not aware of. Thus, the solution is just as described in the note and answer below.
Upvotes: 2
Views: 1576
Reputation: 986
In my case (EF6) marking the owned properties (nested ones) as modified succeeded in the following manner:
var reference = Context.Entry(record).Reference(o => o.ParentProperty);
if (reference.CurrentValue != null)
{
reference.TargetEntry.Property(o => o.ChildProperty1).IsModified = true;
reference.TargetEntry.Property(o => o.ChildProperty2).IsModified = true;
reference.TargetEntry.Property(o => o.ChildProperty3).IsModified = true;
}
The configuration was done as follows:
builder.OwnsOne(l => l.ParentProperty, b =>
{
b.Property(u => u.ChildProperty1).HasConversion(
v => Cryptography.Encrypt(v),
v => Cryptography.Decrypt(v)
);
b.Property(u => u.ChildProperty2).HasConversion(
v => Cryptography.Encrypt(v),
v => Cryptography.Decrypt(v)
);
b.Property(u => u.ChildProperty3).HasConversion(
v => Cryptography.Encrypt(v),
v => Cryptography.Decrypt(v)
);
});
Cryptography
is my internal class for making encryption/decryption.
Upvotes: -1
Reputation: 9437
Wow, it seems that when a new entity is attached to the DbContext
, it actually gets ID (-1 in my case). So, I can set ParentId
even when the target entity is new and has not been added to the database yet.
I wonder whether there are any checks that the new ID is unique (there could already be an entry with ID -1 in database).
Upvotes: 0