“必须通过导航从另一个实体类型引用拥有的实体类型”

时间:2018-08-03 18:42:45

标签: c# entity-framework asp.net-core entity-framework-core

我的应用程序中有一个名为Person的实体。从Person继承的用户有两种类型:Student和Professor。

每个人都有一个设置属性:

public abstract class Person
{
    public Guid UserId { get; set; }
    public string Name { get; set; }

    public PersonSettings Settings { get; set; }
}

public class Student : Person
{
}

public class Professor : Person
{
}

我的PersonSettings类只是几个属性。它不是要存储在数据库中的实体,因此我将其标记为“拥有”:

[Owned]
public class PersonSettings
{
    public bool NotificationsEnabled { get; set; }
    public int GymPassId { get; set; }
}

这些作为json存储在数据库中,我在Person实体配置中使用EF Core转换值对其进行序列化和反序列化:

builder.Property(p => p.Settings).HasConversion(
    s => JsonConvert.SerializeObject(s, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
    s => JsonConvert.DeserializeObject<PersonSettings>(s, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));

但是当我尝试运行我的应用程序并进行数据库迁移时,出现了错误提示

  

拥有实体类型“ PersonSettings”需要通过导航从另一个实体类型中引用。向指向“ PersonSettings”的实体类型添加导航。

我应该在这里做什么?我在错误消息上找不到任何内容。不确定与Person作为抽象类是否有关系。

2 个答案:

答案 0 :(得分:3)

我也无法复制,但是您不需要在这里拥有类型。

使用拥有的类型是对非标量属性使用JSON序列化的替代。使用“拥有的类型”时,类型与引用它的实体一起存储。因此,由于拥有类型EF会使用“设置_通知启用”和“设置_GymPassId”的单独列创建“人”表。

因此,您可以简单地删除OwnedAttribute,并确保在DbContext中不要将其声明为属性类型为DbSet<PersonSettings>的实体。

在选择该方案时,通常会使用“拥有的类型”,因此您可以通过各个PersonSettings属性查询数据库。

使用非标量属性的JSON转换对于拥有集合的情况很有用,因为EF Core当前不支持拥有类型的集合。

答案 1 :(得分:0)

我遇到了同样的问题,为我解决的是遵循文档 here

基本上您想要做的是在您的实体配置中为 OwnsOne 添加一个 Person

builder.OwnsOne(p => p.PersonSettings, ps => {
    //if need be add additional settings here for NotificationsEnabled and GymPassId
});

这将在 Person 和 PersonSettings 之间创建一个“链接”,迁移生成器使用它来构建脚本。