实体框架代码优先-处理继承和组合

时间:2019-03-24 10:24:36

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

我正在自学实体框架核心。实际上,我对整个.net世界来说还比较陌生。

我有以下类似的类(对伪代码表示歉意,实际代码太长了,无法在此处粘贴)。

Account
{
   User UserInfo {get;set;}
}

User
{
   string Email {get;set;}
}

Admin:Account
{
   // some properties
}

我正在尝试使用EF代码优先模式生成数据库表。在上面的类中,我有一个种子例程,如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Account>().HasData(
        new Admin
        {
            UserInfo = new User {Email = "abc@xyz.com"}
        });
}

使用上述方法,当我尝试创建初始迁移时,出现以下错误:

  

不能添加实体类型“ Account”的种子实体,因为提供的值是派生类型“ Admin”的。将派生的种子实体添加到相应的实体类型。

因此,我更改了如下代码(用Admin替换了帐户):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Admin>().HasData(
        new Admin
        {
            UserInfo = new User {Email = "abc@xyz.com"}
        });
}

现在我收到此错误(不确定UserInfoEmail的来源):

  

不能添加实体类型'Admin'的种子实体,因为它已设置了导航'UserInfo'。要播种关系,您需要将相关实体种子添加到'User'并指定外键值{'UserInfoEmail'}。考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'查看所涉及的属性值。

使用代码优先模式时,我无所适从地理解了处理关系的整个概念。有人可以帮我了解上述错误的含义,以及在使用EF代码优先模式时如何处理关系(特别是组成和继承)。

1 个答案:

答案 0 :(得分:0)

第二次尝试已经结束,但是您犯了一个错误:

modelBuilder.Entity<Admin>().HasData(
    new Admin
    {
        UserInfo = new User {Email = "abc@xyz.com"}
    });

看,这里您将UserInfo设置为new User。您的错误意味着您无法在尝试添加User实体时添加Admin实体。而是先添加User,然后再从Admin实体中引用它(看起来Email是您在User实体中的主键):

modelBuilder.Entity<User>().HasData(
    new User
    {
        Email = "abc@xyz.com"
    });
modelBuilder.Entity<Admin>().HasData(
    new Admin
    {
        UserInfoId = "abc@xyz.com"
    });

如果您在UserInfoId类中没有Account,只需添加它即可:

class Account
{
    User UserInfo { get; set; }

    string UserInfoId { get; set; }
}