【问题标题】:Lookup table dilemma查找表困境
【发布时间】:2018-09-20 18:28:37
【问题描述】:

我对如何根据类型返回组织列表有疑问。让我描述一下架构:

查找组织类型表

TypeOfOrganization (table)
-- Id (Guid)[PK]
-- Type (varchar)

示例数据

Id                                   Type                
------------------------------------ --------------------
0C54DECC-6A7B-463F-A160-20F3F270473E Company Location    
B07BE7A9-E569-43F7-B6D9-8A9B19F6D35C Mail Center         
BEA6E923-2170-40B0-9F54-8B6458DB75FD Client              
EBC8C254-FE87-4241-BA37-AD0B1FF5C370 Counsel             
F5EEEF8D-454D-430E-815E-CDFF942D28A0 Company             
5FDC2CD5-A0E9-4656-96C1-F365E67A1E42 Bank                
B4D25CD7-D695-4A6D-9E81-FDD673BDD2A3 Vendor            

将 Orginization 表连接到 OrganizationTypes

OrganizationType (table)
-- Id (Guid)[PK]
-- OrganizationId (Guid)
-- TypeOfOrganizationId (Guid)

示例数据

Id                                   OrganizationId                       TypeOfOrganizationId
------------------------------------ ------------------------------------ ------------------------------------
FECEC824-C5F4-41F8-9F5D-3236371A51B0 448FED23-393C-4019-87AE-0ED64764DFB1 F5EEEF8D-454D-430E-815E-CDFF942D28A0 (Company)
CEA03A1B-9E5F-49A5-BE04-9871A41986CF BEAAA39B-71BD-4F12-A570-FD71FEFD8503 F5EEEF8D-454D-430E-815E-CDFF942D28A0 (Company)
00998ACA-22D2-49D3-B2A2-CE2F3231B38A 1F87F1C5-44B9-4C60-9C38-001975229193 BEA6E923-2170-40B0-9F54-8B6458DB75FD (Client)
50CABBD2-CD55-4781-8BF3-83715216BF1A 6C8DC3B8-5A65-446E-A02B-02354FEDB3E3 BEA6E923-2170-40B0-9F54-8B6458DB75FD (Client)
5E60C5BF-4A36-4546-A3A9-818A1BC6E31B A315020C-268B-4F22-866C-034ACFC22A53 BEA6E923-2170-40B0-9F54-8B6458DB75FD (Client)
56629DFC-A78E-4092-8390-2ABFB21E6CB8 1BF7DAB9-7126-4DC8-A089-0169A52E9FF3 B4D25CD7-D695-4A6D-9E81-FDD673BDD2A3 (Vendor)
280AAE16-1732-44F7-8B8B-0357C5DAD2C4 7FC1BF63-6069-471D-85FC-09F4F5068DD2 B4D25CD7-D695-4A6D-9E81-FDD673BDD2A3 (Vendor)
... and more

仅供参考,此表中不存在组织类型名称的最后一列,我只是将它们放在那里以更好地可视化结构。

组织结构表

Organization (table)
-- Id (Guid) [PK]
-- Name (varchar)

示例数据

Id                                   Organization   
------------------------------------ ---------------
1F87F1C5-44B9-4C60-9C38-001975229193 Client A
6C8DC3B8-5A65-446E-A02B-02354FEDB3E3 Client B
A315020C-268B-4F22-866C-034ACFC22A53 Client C
448FED23-393C-4019-87AE-0ED64764DFB1 Company A
BEAAA39B-71BD-4F12-A570-FD71FEFD8503 Company B
1BF7DAB9-7126-4DC8-A089-0169A52E9FF3 Vendor A
7FC1BF63-6069-471D-85FC-09F4F5068DD2 Vendor B
00674C8A-34B9-46EF-B591-0C5EFBA4EB2B Vendor C
... and more

我的问题是,在不使用常量类的情况下查询特定类型的组织的最佳方法是什么?

例子:

  • 我想获取所有作为客户的组织的列表。
  • 我想获取所有供应商组织的列表。
  • 我想获取所有属于公司的组织的列表。

目前,我在 ASP.NET WebApi 项目中的 Linq 查询以获取供应商列表,如下所示:

var vendors = context.Organizations
    .Where(v => v.OrganizationTypes
       .Any(t => t.TypeOfOrganizationId == Constants.TypeOfOrganization_Vendor);

这是常量类:

public static class Constants
{
    //TypeOfOrganization lookup table
    public static Guid TypeOfOrganization_Client = Guid.Parse("BEA6E923-2170-40B0-9F54-8B6458DB75FD");
    public static Guid TypeOfOrganization_Company = Guid.Parse("F5EEEF8D-454D-430E-815E-CDFF942D28A0");
    public static Guid TypeOfOrganization_Bank = Guid.Parse("5fdc2cd5-a0e9-4656-96c1-f365e67a1e42");
    public static Guid TypeOfOrganization_Location = Guid.Parse("0c54decc-6a7b-463f-a160-20f3f270473e");
    public static Guid TypeOfOrganization_Counsel = Guid.Parse("ebc8c254-fe87-4241-ba37-ad0b1ff5c370");
    public static Guid TypeOfOrganization_Vendor = Guid.Parse("b4d25cd7-d695-4a6d-9e81-fdd673bdd2a3");       
}

我意识到这不是处理这个问题的最佳方法,但目前我无法找到可靠的方法。

【问题讨论】:

  • 您可以尝试 EF 继承,但您在数据库中的表会变得很奇怪。总体而言,对于您的架构,您需要知道类型的 ID。我会考虑翻转你的查询。找到您想要的类型和所有相关的组织。
  • 为什么你有一个从OrganizationsOrganizationTypes 的连接表? Orginization 是否有可能拥有不止一种类型? OrginizationTypes 表的用途是什么?
  • @Blast_dan - 找到我想要的类型是问题所在。我无法根据 Id 查询类型,因为我最初并不知道它,我也无法查询名称,因为这是管理员可以随时更改的内容。
  • @NetMage - 这实际上是一个好问题。我得问问 DBA。
  • 附带一个问题,您的 DBA 是否知道不使用这些 GUID 作为这些表的集群键?

标签: c# sql-server entity-framework linq


【解决方案1】:

也许Guid 不是TypeOfOrganization PK 的最佳选择。由于组织类型不是任意的,而是在应用程序中具有特殊含义,您可以将它们表述为enum

public enum OrgType
{
    None = 0,
    CompanyLocation = 1,
    MailCenter = 2,
    Client = 3,
    Counsel = 4,
    Company = 5,
    Bank = 6,
    Vendor = 7
}

并查询

var vendors = context.Organizations
    .Where(v => v.OrganizationTypes
        .Any(t => t.TypeOfOrganizationId == OrgType.Vendor);

如果您无法更改主键,请为已知组织类型添加一个新的可为空列,映射到 enum。然后将已知类型读入字典,以便通过枚举查找 Guid。

Dictionary<OrgType, Guid> knownOrgGuids = context.OrganizationTypes
    .Where(t => t.KnownType != null)
    .ToDictionary(t => t.KnownType, t => t.TypeOfOrganizationId);
Guid vendorGuid = knownOrgGuids[OrgType.Vendor];
var vendors = context.Organizations
    .Where(v => v.OrganizationTypes
        .Any(t => t.TypeOfOrganizationId == orgGuid);

【讨论】:

  • 这是一个想法,不幸的是,Type 表在 UI 中是可维护的,因此如果创建了新记录,则必须更新枚举。目前,DBA 要求对主键使用 Guid 而不是 int。
  • 添加了枚举存储在附加列中的变体。
【解决方案2】:

这里有几个选择。

  1. 像您正在做的那样创建常量。不过,这可能会让人感到痛苦。
  2. 根据类型的实际名称选择Id。这有点脆弱,因为名称可以更新。
  3. 添加另一个无法更改的标识符列。这可能是一个 int 或另一个名称,它是一个不允许更改的字符串。例如可以在 UI 上创建字段,但不能更新它。您甚至可以在此列上添加索引以使其更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    相关资源
    最近更新 更多