是否可以仅使用EF Code First的数据注释创建双向关系?

时间:2012-02-08 12:41:08

标签: c# .net entity-framework ef-code-first ef-migrations

使用Entity Framework Code First和Entity Framework Migrations(4.3.0-beta1),我想创建一个这样的数据库结构:

Database diagram

如果我这样定义模型:

public class Country
{
    [Required]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(100)]
    public string Name { get; set; }

    public virtual ICollection<State> States { get; set; }

    public virtual ICollection<City> Cities { get; set; }

    [ForeignKey("Capital")]
    public Guid? CapitalCityId { get; set; }

    public virtual City Capital { get; set; }
}

public class State
{
    [Required]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(100)]
    public string Name { get; set; }

    [Required]
    public Guid CountryId { get; set; }

    [Required]
    public virtual Country Country { get; set; }

    public virtual ICollection<City> Cities { get; set; }

    [ForeignKey("Capital")]
    public Guid? CapitalCityId { get; set; }

    public virtual City Capital { get; set; }
}

public class City
{
    [Required]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(100)]
    public string Name { get; set; }

    public Guid? StateId { get; set; }

    public virtual State State { get; set; }

    [Required]
    public Guid CountryId { get; set; }

    [Required]
    public virtual Country Country { get; set; }
}

public class DatabaseContext : DbContext
{
    public DbSet<Country> Countries { get; set; }
    public DbSet<State> States { get; set; }
    public DbSet<City> Cities { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        modelBuilder.Entity<City>().HasOptional(c => c.State).WithMany(s => s.Cities);
        modelBuilder.Entity<City>().HasRequired(c => c.Country).WithMany(c => c.Cities);
        base.OnModelCreating(modelBuilder);
    }
}

我添加了一个迁移,生成了以下迁移代码:

public override void Up()
{
    CreateTable(
        "Countries",
        c => new
            {
                Id = c.Guid(nullable: false),
                Name = c.String(nullable: false, maxLength: 100),
                CapitalCityId = c.Guid(),
            })
        .PrimaryKey(t => t.Id)
        .ForeignKey("Cities", t => t.CapitalCityId)
        .Index(t => t.CapitalCityId);

    CreateTable(
        "States",
        c => new
            {
                Id = c.Guid(nullable: false),
                Name = c.String(nullable: false, maxLength: 100),
                CountryId = c.Guid(nullable: false),
                CapitalCityId = c.Guid(),
            })
        .PrimaryKey(t => t.Id)
        .ForeignKey("Countries", t => t.CountryId)
        .ForeignKey("Cities", t => t.CapitalCityId)
        .Index(t => t.CountryId)
        .Index(t => t.CapitalCityId);

    CreateTable(
        "Cities",
        c => new
            {
                Id = c.Guid(nullable: false),
                Name = c.String(nullable: false, maxLength: 100),
                StateId = c.Guid(),
                CountryId = c.Guid(nullable: false),
            })
        .PrimaryKey(t => t.Id)
        .ForeignKey("States", t => t.StateId)
        .ForeignKey("Countries", t => t.CountryId)
        .Index(t => t.StateId)
        .Index(t => t.CountryId);

}

导致结构正确。

我想知道是否可以在不使用流畅的API的情况下实现此结果。

如果我省略了流畅的API说明,请执行以下操作:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    //modelBuilder.Entity<City>().HasOptional(c => c.State).WithMany(s => s.Cities);
    //modelBuilder.Entity<City>().HasRequired(c => c.Country).WithMany(c => c.Cities);
    base.OnModelCreating(modelBuilder);
}

然后在Cities表中创建另外两个字段:

CreateTable(
    "Cities",
    c => new
        {
            Id = c.Guid(nullable: false),
            Name = c.String(nullable: false, maxLength: 100),
            StateId = c.Guid(),
            CountryId = c.Guid(nullable: false),
            State_Id = c.Guid(),
            Country_Id = c.Guid(),
        })
...

但是,流畅的API指令似乎没有添加比使用Code First约定已经发现的信息更多的信息。

我想知道是否有更好的方法来创建这种关系,尤其是那种不需要流畅API的关系。

代码段以gist

的形式提供

0 个答案:

没有答案