【问题标题】:Entity Framework : should I provide double-side relationship configuration?实体框架:我应该提供双边关系配置吗?
【发布时间】:2016-09-24 03:33:53
【问题描述】:

我的问题很简单:这里我有两个具有一对多关系的类。 让我们举个例子: 样本取自 Julia Lerman “Programming Entity Framework : Code First”一书

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; }
}

这里使用 FluentApi 进行配置:

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);

HasMany(p=>p.Lodgings).WithRequired(l=>l.Destination);

在 Destination 和 Lodging 之间的关系上提供相同的结果。

如果我只定义其中一个规则,它也很有效。 在双方都定义相同的规则是一种好习惯还是一方声明可以?

【问题讨论】:

    标签: c# entity-framework


    【解决方案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】:

      两种配置都非常好。如果您真的需要它,这是一个很好的做法。如果不保持关系简单,并且仅在有意义的实体中公开导航属性。 (这更多是与您的实体模型相关的问题,而不是 EF)

      【讨论】:

        【解决方案3】:

        只定义一次(例如)

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-02
          • 1970-01-01
          相关资源
          最近更新 更多