2017-03-01 51 views
0

我是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); 
} 

非常感谢你借给猥自您的时间和关注这个问题。

+0

查理,只是一个提示:尽量找一些关于TPT,TPH和TPC。关于这个话题有两个不同的“世界”,他们是数据库você类模型。当谈到“类模型”时,你有一些模式(比如常用的抽象类的使用),但是当你不得不把它放在数据库(它没有那些概念)时,你有一些策略应该知道。 –

+0

关于你的代码,它对我来说看起来并不奇怪(没有反模式imao)。 –

+0

谢谢你,马塞洛。我非常感谢您对谦卑代码的评估。我研究了实体框架内的不同表格生成选项。我还没有掌握这一点,但到目前为止,我发现根据型号类型,有时最好将TPH和TPC结合起来。例如,地址可能最适合共享多个外键列,但员工和客户不应共享表格作为人员模型 –

回答

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

然后抽象一个人类(无论名字)。

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

public class People : Human 
{ 
} 

public class Merchant : Human 
{ 
} 

这种感觉对我来说更自然。

+0

我很感谢您的洞察力。就商家而言,我的意思是“商业”,因此地址可能属于除人之外的东西。我仍然需要为“非人类”创建一个单独的课程。无论如何,你的回答让我想到 - 猫可以用很多方式剥皮。也许可以为“可寻址”模型实现一个接口。 –