【问题标题】:EF 6 not generating all inherited fields for some classesEF 6 没有为某些类生成所有继承的字段
【发布时间】:2018-02-01 12:13:47
【问题描述】:
public abstract class TableBase
{
    [Required]
    public DateTime DateInsert { get; set; }
    public DateTime? DateUpdate { get; set; }
    [Required]
    public AppUser UserInsert { get; set; }
    public AppUser UserUpdate { get; set; }        
}

public class AppUser:TableBase
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public string LoginName { get; set; }
    [Required]
    public string PasswordStored { get; set; }        
}

public class SandorTestDBContext : DbContext
{
    public SandorTestDBContext() : base("SandorTestDB")
    {    
    }

    public DbSet<AppUser> AppUsers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
        base.OnModelCreating(modelBuilder);
    }
}

鉴于上述类,可以假设 SQLserver 中的 AppUser 表将包含这两个类的所有字段。但该表缺少 UserUpdate_Id 字段。

TABLE [dbo].[AppUsers](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NOT NULL,
[LoginName] [nvarchar](max) NOT NULL,
[PasswordStored] [nvarchar](max) NOT NULL,
[DateInsert] [datetime] NOT NULL,
[DateUpdate] [datetime] NULL,
[UserInsert_Id] [int] NOT NULL

另一方面,添加以下类:

public class Company : TableBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string OldCompanyReference { get; set; }  
}

在上下文中添加 DbSet 确实会生成所有字段

public DbSet<Company> Companies { get; set; }

TABLE [dbo].[Companies](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[OldCompanyReference] [nvarchar](max) NULL,
[DateInsert] [datetime] NOT NULL,
[DateUpdate] [datetime] NULL,
[UserInsert_Id] [int] NOT NULL,
[UserUpdate_Id] [int] NULL,

那我错过了什么???

【问题讨论】:

    标签: c# entity-framework-6 sql-server-2016


    【解决方案1】:

    它与继承没有任何共同之处 - 如果您删除继承并将TableBase 属性复制到AppUser,也会发生同样的情况。

    问题在于 AppUser 有 2 个 self 引用 - UserInsertUserUpdate。由于第一个标记为必需,第二个是可选的,按照惯例,EF 将它们映射到单个一对一的 FK 关系,UserUpdateUserInsert 的反向导航属性。这当然不是你的本意。

    像往常一样,当 EF 常规映射无法产生预期结果时,您需要使用数据注释和/或流式 API。在这种特殊情况下 - 流畅的 API。最低要求是这样的:

    modelBuilder.Entity<AppUser>()
        .HasOptional(e => e.UserInsert)
        .WithMany();
    

    通过这种方式,您告诉 EF 与一侧的 UserInsert 引用导航属性和另一侧的没有集合导航属性创建一对多关系。这样做的额外效果是,当 EF 找到未映射的 UserUpdate 引用导航属性时,按照惯例,它将创建另一个一对多的单向关系。最后将创建两个 FK 列,与非自引用实体示例一样。

    另请注意,在自引用实体AppUser 中,UserInsert 不是必需的,否则您将无法创建任何AppUser 记录。这就是我使用HasOptional 而不是HasRequired 的原因,它覆盖了仅针对该实体的基类属性Required 数据注释。

    【讨论】:

      猜你喜欢
      • 2021-07-24
      • 2018-09-28
      • 2019-12-20
      • 2018-03-05
      • 2022-01-04
      • 1970-01-01
      • 2022-08-21
      • 2016-02-09
      • 1970-01-01
      相关资源
      最近更新 更多