如何创建查找表并定义关系

Posted

技术标签:

【中文标题】如何创建查找表并定义关系【英文标题】:How to create Lookup table and define relationships 【发布时间】:2015-06-02 17:38:42 【问题描述】:

正如您在下面看到的,有一个枚举值的查找表,我想在表的枚举值和查找表的 LookupKey 列之间创建关系(而不是 ID 列查找表)。

查找表:

ID   | LookupType | LookupKey | LookupValue |
101  | Status     | 0         | Passive     | 
106  | Gender     | 1         | Male        | 
113  | Status     | 1         | Active      | 
114  | Gender     | 2         | Female      | 
118  | Status     | 2         | Cancelled   | 

主表:

ID | Status     | Gender    | Name              | ...
1  | 0          | 1         | John Smith        | ...
2  | 1          | 2         | Christof Jahnsen  | ...
3  | 2          | 1         | Alexi Tenesis     | ...
4  | 0          | 2         | Jurgen Fechtner   | ...
5  | 1          | 2         | Andreas Folk      | ...

但是,当在DataAnnotations - InverseProperty Attribute 上使用 PK-FK 关系和 InverseProperty 时,关系是使用 Lookup 表的 ID 列创建的,我无法与 LookupKey 列建立关系。你能举例说明如何实现这一目标吗?

【问题讨论】:

为什么要投反对票而不是回答??? 为什么不想使用 ID 列?您不能单独使用查找键,因为它不是唯一的。我想您可以做一些棘手的事情,例如 .HasForeignKey(m => new m.GenderLookupType, m.GenderLookupKey) 但现在您的主表中每个关系都有 2 个字段。 除了 ID 列之外,它是否有助于我使 LookupKey 列成为主键?实际上,我目前对两者都使用 ID 列:作为“ID”和“LookupKey”。但是,在这种情况下,查找键会变成 1、2、7、25,因为将来会添加新值。另一方面,我希望按顺序创建 LookupKey 值,即 1、2、3、4、.... 等。那么,使用额外的键值(即“LookupKey”)是不是坏主意?当开发人员尝试使用查找表时,这种情况下的一般用法是什么?他们是否对记录和 LookupKey 都使用 ID 列?你能澄清一下吗? 【参考方案1】:

我们在这里有一个通用的查找表。它看起来和你的很相似。 LookupData 具有 LookupTypes 的主键和外键,相当于您的枚举和值。我们可能还有一些其他简单的字段,例如在 LookupType 元数据表中标识的标志或代码。然后在主表中,我们可能有指向 LookupData.Id 字段的“GenderLookupId”。 ID 本身没有任何意义,可以按任意顺序输入。如果您希望性别 1 和 2 有意义,您可能应该为此添加另一个属性(请参阅代理键)。

数据示例:

查找类型

ID    Description    CodeDesc        BooleanDesc  
1     Genders        Gender Code     NULL
2     Races          Race Code       Is Active

查找数据

ID    LookupTypeId    Description    Code    Boolean
789   1               Male           M       NULL
790   2               White          W       True
791   1               Female         F       NULL
792   2               Hispanic       H       False

主名称表

NameId   Name          GenderLookupId   RaceLookupId
1234     Joe Smith     789              790
1235     Mary Meyers   791              792

类:

public class LookupType

    public int Id  get; set; 
    public string Description  get; set; 
    public string CodeDescription  get; set; 
    public string BooleanDescription  get; set; 

public class LookupData

    public int Id  get; set; 
    public int LookupTypeId  get; set; 
    public string Description  get; set; 
    public string Code  get; set; 
    public bool? BooleanValue  get; set; 
    public LookupType LookupType  get; set;  

public class Name

    public int Id  get; set; 
    public string FullName  get; set; 
    public int? GenderLookupId  get; set; 
    public LookupData Gender  get; set;  

查找数据配置:

HasRequired(p => p.LookupType).WithMany(p=>p.LookupData).HasForeignKey(p=>p.LookupTypeId).WillCascadeOnDelete(false);

名称配置:

HasOptional(p => p.Gender).WithMany(p=>p.Name).HasForeignKey(p=>p.GenderLookupId).WillCascadeOnDelete(false);

【讨论】:

非常感谢您的精彩解释。据我所知,通过创建一个带有 ID、LookupType 和 LookupKey 列的新表,我的方法似乎类似于这种方法。那么,能否请您一一说明以下方法? 1) 将我的表转换为您的示例时,我创建了一个新表来定义 LookupType(即 Gender、Status 等),它是 Lookup 表的 TypeID 的 FK。在这种情况下,我会在查找表上重复代码而不是类型描述。真的吗?这还有其他好处吗? 2) 通过使用这种方法,我将继续使用“InverseProperty”以便为同一个表(LookupData)使用多个FK?我的意思是,在主表中添加引用 LookupData 表的导航属性是不够的。例如,对于 Gender 列 LookupData 使用导航属性,对于 Race 也将使用它。在这种情况下,应使用特殊方法来引用与“InverseProperty”相同的表。你用什么? 1 - 这只是简单的数据库规范化。 sqlservercentral.com/blogs/abhijit_desai/2010/09/07/… 2 - 我们不会将导航集合放在子查找中 - 即种族或性别中没有名称集合,因为我们永远不需要以这种方式导航。我们只需在 Name 中添加一个流畅的配置,例如 ...HasOptional(n => n.RaceLookup).WithMany().HasForeignKey(n => n.RaceLookupId).WillCascadeOnDelete(false);

以上是关于如何创建查找表并定义关系的主要内容,如果未能解决你的问题,请参考以下文章

如何创建联结表并添加索引?

如何在 has_many 关系中搜索?

CoreData:如何建模循环多对多关系

在父表和查找表之间创建 Eloquent 关系?

二食堂Beta - 发布声明

二食堂Beta - 发布声明