将导航属性应用于抽象模型(如地址)的最佳模式?

时间:2017-03-01 22:49:32

标签: c# entity-framework

我是SQL和实体框架的新手。我就围绕这两个概念的设计问题寻求帮助。

在建模一对多关系时,我理解在关系的从属端有一个外键是必要的。这意味着抽象模型(如地址)必须包含实现多个地址的任何其他模型的导航属性。

代替这一点,我想知道是否使用继承来向抽象模型添加导航属性是正确的方法,或者如果可能的话,有更好的方法来实现我想要做的事情。在我对实体框架所做的所有阅读中,我都没有看到过这种模式。因此,我觉得这必须是反模式,必须有更好的方法。请参阅下面的例子,我的意思是:

public abstract class BaseEntity
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public Guid RowId { get; set; }

    [Timestamp]
    public byte[] RowVersion { get; set; }
}

public abstract class Address : BaseEntity
{
    public string Street1 { get; set; }
    public string Street2 { get; } set; }
    public string City { get; set; }
    public string StateProvince { get; set; }
    public string Zipcode { get; set; }
    public string Country { get; set; }
}

public class PersonAddress : Address
{
    public Guid PersonId { get; set; }
    public virtual Person Person { get; set; }
}

public class MerchantAddress : Address
{
    public Guid MerchantId { get; set; }
    public virtual Merchant Merchant { get; set; }
}

public class Person : BaseEntity
{
    // person properties

    public ICollection<PersonAddress> Addresses { get; set; }
}

public class Merchant : BaseEntity
{
    // merchant properties

    public ICollection<MerchantAddress> Addresses { get; set; }
}

最后是流利的api:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
                .HasMany(p => p.Addresses)
                .WithRequired(a => a.Person)
                .HasForeignKey(a => a.PersonId);

    modelBuilder.Entity<Merchant>()
                .HasMany(m => m.Addresses)
                .WithRequired(a => a.Merchant)
                .HasForeignKey(a => a.MerchantId);
}

非常感谢您通过这个问题为自己的时间和精力提供谦逊的自我。

1 个答案:

答案 0 :(得分:0)

这似乎是正确的方法。

你也可以采用相反的方式。

public class Address : BaseEntity // Not abstract
{
    public int HumanId { get; set; }
    public Human Human { get; set; }

    public string Street1 { get; set; }
    public string Street2 { get; } set; }
    public string City { get; set; }
    public string StateProvince { get; set; }
    public string Zipcode { get; set; }
    public string Country { get; set; }
}

然后抽象一个Human类(无论名称)。

public abstract class Human : BaseEntity
{
    public ICollection<Address> Addresses { get; set; }
}

public class People : Human
{
}

public class Merchant : Human
{
}

这对我来说感觉更自然。