实体框架:我应该提供双面关系配置吗?

时间:2016-09-23 19:11:07

标签: c# entity-framework

我的问题非常简单:这里有两个一对多关系的课程。 我们来看一个样本:  摘自Julia Lerman的书"编程实体框架:代码优先"

push (@{ $hash2{$numbers} }, $items)

这里配置了FluentApi:

public class Destination
{
    public int DestinationId { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }
    public string Description { get; set; }
    public byte[]  Photo { get; set; }
    public ICollection<Lodging> Lodgings { get; set; }

    public Destination()
    {
        Lodgings = new List<Lodging>();
    }
}

public class Lodging
{
    public int LodgingId { get; set; }
    public string Name { get; set; }
    public string Owner { get; set; }
    public bool IsResort { get; set; }
    public decimal MilesFromNearestAirport { get; set; }
    public Destination Destination { get; set; }
    public int DestinationId { get; set; }
}

我想那行

public class LodgingConfiguration : EntityTypeConfiguration<Lodging>
{
    public LodgingConfiguration()
    {
        Property(p => p.Name).IsRequired().HasMaxLength(200);
        HasRequired(p => p.Destination).WithMany(p => p.Lodgings);
    }
}

public class DestinationConfiguration : EntityTypeConfiguration<Destination>
{
    public DestinationConfiguration()
    {
        Property(p => p.Name).IsRequired().HasMaxLength(100);
        Property(p => p.Description).HasMaxLength(500);
        Property(p => p.Photo).HasColumnType("image");
        HasMany(p=>p.Lodgings).WithRequired(l=>l.Destination);
    }
}

HasRequired(p => p.Destination).WithMany(p => p.Lodgings);

在目的地和住宿之间的关系上提供相同的结果。

如果我只定义其中一条规则,它也可以正常工作。 在双方定义相同的规则是一个好习惯还是单边声明是好的?

3 个答案:

答案 0 :(得分:1)

这两种配置都是罚款。如果你真的需要它,这是一个很好的做法。如果不保持关系简单,只显示有意义的实体中的导航属性。 (这与您的实体模型相关的问题比EF更多)

答案 1 :(得分:1)

如果您对这三种变体add-migration执行了以下结果:

  

使用住宿和目的地配置类型中的映射

public override void Up()
{
    CreateTable(
        "dbo.Lodgings",
        c => new
            {
                LodgingId = c.Int(nullable: false, identity: true),
                Name = c.String(nullable: false, maxLength: 200),
                Owner = c.String(),
                IsResort = c.Boolean(nullable: false),
                MilesFromNearestAirport = c.Decimal(nullable: false, precision: 18, scale: 2),
                Destination_DestinationId = c.Int(nullable: false),
            })
        .PrimaryKey(t => t.LodgingId)
        .ForeignKey("dbo.Destinations", t => t.Destination_DestinationId, cascadeDelete: true)
        .Index(t => t.Destination_DestinationId);

    CreateTable(
        "dbo.Destinations",
        c => new
            {
                DestinationId = c.Int(nullable: false, identity: true),
                Name = c.String(nullable: false, maxLength: 100),
                Country = c.String(),
                Description = c.String(maxLength: 500),
                Photo = c.Binary(storeType: "image"),
            })
        .PrimaryKey(t => t.DestinationId);

}
  

从住宿配置类型中删除映射

public override void Up()
{
    CreateTable(
        "dbo.Lodgings",
        c => new
            {
                LodgingId = c.Int(nullable: false, identity: true),
                Name = c.String(nullable: false, maxLength: 200),
                Owner = c.String(),
                IsResort = c.Boolean(nullable: false),
                MilesFromNearestAirport = c.Decimal(nullable: false, precision: 18, scale: 2),
                Destination_DestinationId = c.Int(nullable: false),
            })
        .PrimaryKey(t => t.LodgingId)
        .ForeignKey("dbo.Destinations", t => t.Destination_DestinationId, cascadeDelete: true)
        .Index(t => t.Destination_DestinationId);

    CreateTable(
        "dbo.Destinations",
        c => new
            {
                DestinationId = c.Int(nullable: false, identity: true),
                Name = c.String(nullable: false, maxLength: 100),
                Country = c.String(),
                Description = c.String(maxLength: 500),
                Photo = c.Binary(storeType: "image"),
            })
        .PrimaryKey(t => t.DestinationId);

}
  

从目标配置类型中删除映射

public override void Up()
{
    CreateTable(
        "dbo.Lodgings",
        c => new
            {
                LodgingId = c.Int(nullable: false, identity: true),
                Name = c.String(nullable: false, maxLength: 200),
                Owner = c.String(),
                IsResort = c.Boolean(nullable: false),
                MilesFromNearestAirport = c.Decimal(nullable: false, precision: 18, scale: 2),
                Destination_DestinationId = c.Int(nullable: false),
            })
        .PrimaryKey(t => t.LodgingId)
        .ForeignKey("dbo.Destinations", t => t.Destination_DestinationId, cascadeDelete: true)
        .Index(t => t.Destination_DestinationId);

    CreateTable(
        "dbo.Destinations",
        c => new
            {
                DestinationId = c.Int(nullable: false, identity: true),
                Name = c.String(nullable: false, maxLength: 100),
                Country = c.String(),
                Description = c.String(maxLength: 500),
                Photo = c.Binary(storeType: "image"),
            })
        .PrimaryKey(t => t.DestinationId);

}

如您所见,生成的代码(在本例中为Sql server)完全相同。它始终是一种风格问题,并且要保持一致。您可以在父配置类型或任何其他样式中显式设置子映射。

Here是关于这个主题的非常好的答案。

答案 2 :(得分:1)

只定义一次(例如)

modelBuilder.Entity<Student>()
    .HasRequired<Course>(s => s.Course)
    .WithMany(s => s.Students);

请记住,您需要维护代码。在两个单独的表示/位置中具有相同的信息是错误的处方。你认为团队中的每个人都会那么细致吗?