Owned type property not persisting for a modified entity in EF Core

你说的曾经没有我的故事 提交于 2021-01-22 10:28:34

问题


I'm trying to achieve something in EF Core that worked very well for me in EF 6.

I'm serializing the contents of a List<T> property as a Json string in the DB. <T> can be pretty much anything, since Json.Net takes care of serializing whatever we throw at it. My collection exposes a Json string property and takes care of serializing/deserializing itself.

This approach is convenient and efficient for structured nested data where a relational model would bring needless overhead and complexity.

In EF 6 I would do something like this:

[ComplexType]
public class SelfSerializingCollection<T> : Collection<T>
{
    public void AddRange(IEnumerable<T> collection)
    {
        foreach (var item in collection)
        {
            Add(item);
        }
    }

    protected string Json
    {
        get { return JsonConvert.SerializeObject(this); }
        private set
        {
            Clear();

            if (value == null)
            {
                return;
            }

            AddRange(JsonConvert.DeserializeObject<T[]>(value));
        }
    }
}

EF 6 doesn't support mapping generic types, so we'd provide a concrete implementation for each type of List we might want:

public class PhoneNumberCollection : SelfSerializingCollection<PhoneNumber> { }

And then use it like this:

public class Contact {
    public PhoneNumberCollection PhoneNumbers { get; set; }
}

And that was it. Now, I'm trying to achieve the same in EF Core 2.0.

Here's what I have so far. The SelfSerializingCollection<T> class is unchanged.

public class Contact {
    // EF Core supports generic types so we don't need a concrete implementation
    // for each collection type.
    public SelfSerializingCollection<PhoneNumber> PhoneNumbers { get; set; }
}

public class MyDbContext : DbContext
{
    // ...

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // EF Core does not support the [ComplexType] attribute
        // but we now have .OwnsOne() in EF Core 2
        modelBuilder.Entity<Contact>().OwnsOne(p => p.PhoneNumbers);
    }
}

So far so good. EF Core maps the PhoneNumbers_Json column in the DB. Reading and creating new entries works just fine.

But, unlike in EF 6, any changes to the PhoneNumbers collection on an existing entity are not being persisted back to the database. I am updating in a typical PUT method with _context.Entry(contactModelFromRequestBody).State = EntityState.Modified; - same as before. But for some reason, EF Core is not persisting my Json string property back to the DB for a Modified entity.

Any ideas?


回答1:


EF Core treats owned types like entity types w/o own identity, hence properties that point to owned type are treated as navigation properties. And setting the parent entity state to Modified does not cascade to navigation properties.

However the Update method of DbContext or DbSet does cascade, so instead of

_context.Entry(contactModelFromRequestBody).State = EntityState.Modified;

you should use

_context.Update(contactModelFromRequestBody);



回答2:


It seems necessary to manually set the modified entity state for my owned types:

_context.Entry(contact).Reference(p => p.PhoneNumbers)
    .TargetEntry.State = EntityState.Modified;

This does the trick, although I'm still hoping to find a more general solution that doesn't require me to mark all the owned properties like this on every update.



来源:https://stackoverflow.com/questions/46872428/owned-type-property-not-persisting-for-a-modified-entity-in-ef-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!