【问题标题】:Owned type property not persisting for a modified entity in EF Core拥有的类型属性不会为 EF Core 中的已修改实体保留
【发布时间】:2018-04-03 00:03:11
【问题描述】:

我正在尝试在 EF Core 中实现一些在 EF 6 中非常适合我的东西。

我将List<T> 属性的内容序列化为数据库中的Json 字符串。 <T> 几乎可以是任何东西,因为 Json.Net 负责序列化我们扔给它的任何东西。我的集合公开了一个 Json 字符串属性并负责序列化/反序列化本身。

对于关系模型会带来不必要的开销和复杂性的结构化嵌套数据,这种方法既方便又高效。

在 EF 6 中,我会这样做:

[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 不支持映射泛型类型,因此我们将为我们可能需要的每种类型的 List 提供具体实现:

public class PhoneNumberCollection : SelfSerializingCollection<PhoneNumber> { }

然后像这样使用它:

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

就是这样。现在,我正在尝试在 EF Core 2.0 中实现同样的目标。

这是我目前所拥有的。 SelfSerializingCollection&lt;T&gt; 类没有改​​变。

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

到目前为止一切顺利。 EF Core 映射数据库中的 PhoneNumbers_Json 列。阅读和创建新条目就可以了。

但是,与 EF 6 不同,对现有实体上的 PhoneNumbers 集合的任何更改不会被持久化回数据库。我正在使用_context.Entry(contactModelFromRequestBody).State = EntityState.Modified; 以典型的 PUT 方法进行更新 - 与以前相同。但由于某种原因,EF Core 没有将我的 Json 字符串属性持久化回数据库中以获取 Modified 实体。

有什么想法吗?

【问题讨论】:

    标签: c# entity-framework entity-framework-core ef-core-2.0


    【解决方案1】:

    EF Core 将拥有的类型视为没有自己身份的实体类型,因此指向拥有类型的属性被视为导航属性。并且将父实体状态设置为Modified 不会级联到导航属性。

    但是DbContextDbSetUpdate 方法确实是级联的,所以不是

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

    你应该使用

    _context.Update(contactModelFromRequestBody);
    

    【讨论】:

    • 好多了 :) 谢谢。
    【解决方案2】:

    似乎有必要为我拥有的类型手动设置修改后的实体状态:

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

    这可以解决问题,尽管我仍然希望找到一个更通用的解决方案,不需要我在每次更新时都像这样标记所有拥有的属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-27
      • 1970-01-01
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 2021-04-28
      • 1970-01-01
      相关资源
      最近更新 更多