WithRequiredPrincipal,为什么还要定义Required或ForeignKey才能编译?

时间:2016-02-05 22:21:02

标签: entity-framework relational-database fluent

public class Admin : EntityTypeConfiguration<Admin>
{
    //[ForeignKey("Blog")] -- If I enable this, it compiles
    public int AdminId { get; set; }
    public string AdminName { get; set; }
    public string AdminPicture { get; set; }

    //[Required] -- Or If I enable this, it compiles
    public virtual Blog Blog { get; set; }
}

public class Blog : EntityTypeConfiguration<Blog>
{
    public int BlogId { get; set; }
    public string BlogName { get; set; }
    public string BlogUrl { get; set; }

    public virtual Admin Admin { get; set; }

    public Blog()
    {
        HasRequired(a => a.Admin).WithRequiredPrincipal(b=>b.Blog);
    }
}

只要我定义了HasRequired和WithRequiredPrincipal键,为什么VS仍会创建以下错误。

  

无法确定类型'Dummy.Models.Blog'和'Dummy.Models.Admin'之间关联的主要结尾。必须使用关系流畅API或数据注释显式配置此关联的主要结尾。

第二件事是,即使我启用[必需]或[ForeingKey] attr。,在edmx设计器中,我只看到1 - 0..1但我必须看到1 - 1(两端都需要)

1 个答案:

答案 0 :(得分:1)

数据库级别无法实现1-1关系,因为您无法同时插入两行。 1-1仅适用于类验证级别。

要建立1-1关系,依赖实体的主键必须是主体的外键;这是建立1-1关系的唯一途径。因此,您必须进行以下更改(考虑到您使用的是EF Code First):

public class Admin
{
    public int AdminId { get; set; }
    public string AdminName { get; set; }
    public string AdminPicture { get; set; }

    public virtual Blog Blog { get; set; }
}

博客不应该拥有自己的BlogId,因为博客属于管理员,管理员只能拥有一个博客(1-1关系)。如果您使用AdminId FK创建BlogId,您将建立1-n关系。此外,不要将实体类与映射类混合,它们应该是不同的东西。请参阅以下示例:

public class Blog
{
    public int AdminId { get; set; } //PK AND FK
    public string BlogName { get; set; }
    public string BlogUrl { get; set; }

    public virtual Admin Admin { get; set; }         
}

使用映射类创建关系:

public class BlogMapping : EntityTypeConfiguration<Blog>
{
    public BlogMapping()
    {
        HasKey(i => i.AdminId);

        HasRequired(a => a.Admin)
            .WithRequiredDependent(i => i.Blog);
    }
}

在dbContext类中注册映射:

public class MyDbContext : DbContext
{
    public DbSet<Admin> Admins { get; set; }
    public DbSet<Blog> Blogs { get; set; }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new BlogMapping());
    }
}

这将生成以下迁移:

CreateTable(
    "dbo.Admins",
    c => new
        {
            AdminId = c.Int(nullable: false, identity: true),
            AdminName = c.String(),
            AdminPicture = c.String(),
        })
    .PrimaryKey(t => t.AdminId);

CreateTable(
    "dbo.Blogs",
    c => new
        {
            AdminId = c.Int(nullable: false),
            BlogName = c.String(),
            BlogUrl = c.String(),
        })
    .PrimaryKey(t => t.AdminId)
    .ForeignKey("dbo.Admins", t => t.AdminId)
    .Index(t => t.AdminId);

希望这有帮助!