代码或查找表的最佳实践

时间:2009-04-15 20:02:06

标签: domain-driven-design lookup dbtable

[更新]选择的方法如下,作为对此问题的回答

嗨,

我一直在寻找这个主题,但我找不到我想要的东西......

使用代码表我的意思是:像'婚姻状况',性别,特定的法律或社会状态...更具体地说,这些类型只设置属性,项目不会很快改变(但可能)。属性是Id,名称和描述。

我想知道如何在以下技术中处理这些问题:

    数据库中的
  • (多个表,一个表有不同的代码键......?)

  • 创建类(可能类似于使用ICode.Name和ICode.Description继承ICode)

  • 为此创建视图/演示者:应该有一个包含所有视图/演示者的屏幕,所以类型列表(性别,婚姻状态......),然后是该类型的值列表一个名字&值列表中每个项目的描述。

这些都出现在每个项目中,因此必须有一些关于如何处理这些问题的最佳实践......

为了记录,我并不是真的喜欢在这些情况下使用枚举...在这里使用它们的任何争论也是受欢迎的。

[关注]

好的,CodeToGlory和Ahsteele给了我一个很好的答案。让我们改进这个问题。

假设我们不是在谈论性别或婚姻状况,这些价值肯定不会改变,而是关于具有名称和描述的“东西”,但仅此而已。例如:社会状况,法律状态。

UI: 我只想要一个屏幕。带有possibe NameAndDescription类型的列表框(我只是称之为),列表框中包含所选NameAndDescription类型的可能值,然后是所选NameAndDescription类型项的名称和描述字段。

如何在View&主持人?我发现这里的困难是需要从类名中提取NameAndDescription类型吗?

DB: 多个与单个查找表的优缺点是什么?

6 个答案:

答案 0 :(得分:2)

使用数据库驱动的代码表非常有用。您可以执行以下操作:定义数据的生命周期(使用开始日期和结束日期),实时向表中添加数据,这样您就不必部署代码,并且可以允许用户(当然具有正确的权限)通过管理员屏幕添加数据。

我建议始终使用自动编号主键而不是代码或说明。这允许您在不同的时间段内使用多个代码(具有相同名称但不同的描述)。此外,大多数DBA(根据我的经验)使用自动编号而不是基于文本的主键。

我会为每个编码列表使用一个表。您可以将多个代码全部放入一个不相关的表中(使用排序矩阵),但这样会变得混乱,我只发现了一些甚至有用的情况。

答案 1 :(得分:1)

这里有几件事:

  1. 使用明确清除且不会更改的枚举。例如,MaritalStatus,Gender等。

  2. 将查找表用于上述未修复的项目,并可能随时间变化,增加/减少。

  3. 在数据库中拥有查找表非常典型。在业务层中定义一个可以与您的视图/演示文稿一起使用的键/值对象。

答案 2 :(得分:1)

我决定采用这种方法:

CodeKeyManager mgr = new CodeKeyManager();
CodeKey maritalStatuses = mgr.ReadByCodeName(Code.MaritalStatus);

其中:

  • CodeKeyManager可以从DB检索CodeKeys(CodeKey = MaritalStatus)
  • Code是一个充满常量的类,返回字符串,因此Code.MaritalStatus =“maritalStatus”。这些常量映射到CodeKey表> CodeKeyName
  • 在数据库中,我有2个表:
    • CodeKey with Id,CodeKeyName
    • CodeValue with CodeKeyId,ValueName,ValueDescription

DB:

alt text http://lh3.ggpht.com/_cNmigBr3EkA/SeZnmHcgHZI/AAAAAAAAAFU/2OTzmtMNqFw/codetables_1.JPG

班级代码:

public class Code
{
    public const string Gender = "gender";
    public const string MaritalStatus = "maritalStatus";
}

Class CodeKey:

public class CodeKey
{
    public Guid Id { get; set; }
    public string CodeName { get; set; }

    public IList<CodeValue> CodeValues { get; set; }
}

Class CodeValue:

public class CodeValue
{
    public Guid Id { get; set; }

    public CodeKey Code { get; set; }

    public string Name { get; set; }
    public string Description { get; set; }

}

到目前为止,我发现最简单,最有效的方式:

  • 所有代码数据都可以相同的方式显示(在同一视图/演示者中)
  • 我不需要为即将到来的每个代码表创建表和类
  • 但我仍然可以轻松地将它们从数据库中取出并使用CodeKey常量轻松使用它们......
  • NHibernate也可以轻松处理这个问题

我唯一还在考虑的是丢弃GUID ID并使用字符串(nchar)代码来实现业务逻辑中的可用性。

感谢您的回答!如果对这种方法有任何评论,请做!

答案 3 :(得分:0)

我倾向于使用表格表示这种类型的数据。最终,如果您需要捕获数据,则需要存储数据。出于报告目的,最好有一个可以通过密钥绘制数据的地方。出于规范化目的,我发现单用途查找表比多用途查找表更容易。

这就是说,对于不会像性别等那样改变的事情,枚举非常有用。

答案 4 :(得分:0)

为什么每个人都希望复杂化代码表?是的,有很多,但它们很简单,所以保持这种方式。就像对待其他对象一样对待它们。你是域名的一部分,所以将它们建模为域名的一部分,没什么特别的。如果你不想要它们不可避免地需要更多的属性或功能,你将不得不撤消当前使用它的所有代码并重做它。

每个当然一个表(用于参照完整性,以便它们可用于报告)。

对于课程,当然还有一个,因为如果我写一个方法来接收“性别”对象,我不希望能够意外地将它传递给“MarritalStatus”!让编译帮助你排除运行时错误,这就是它的原因。每个类都可以简单地继承或包含CodeTable类或其他任何类,但这只是一个实现帮助程序。

对于UI,如果确实使用了继承的CodeTable,我想你可以使用它来帮助你并在一个UI中维护它。

作为一项规则,不要搞乱数据库模型,不要弄乱业务模型,但是你想在UI模型中稍微搞砸一下,那并不是那么糟糕。

答案 5 :(得分:0)

我想考虑进一步简化此方法。代替3个表来定义代码(Code,CodeKey和CodeValue),仅一个包含代码类型和代码值的表又如何呢?毕竟,所有代码类型只是另一个代码列表。

也许是这样的表定义:

CREATE TABLE [dbo].[Code](
    [CodeType] [int] NOT NULL,
    [Code] [int] NOT NULL,
    [CodeDescription] [nvarchar](40) NOT NULL,
    [CodeAbreviation] [nvarchar](10) NULL,
    [DateEffective] [datetime] NULL,
    [DateExpired] [datetime] NULL,
CONSTRAINT [PK_Code] PRIMARY KEY CLUSTERED 
(
    [CodeType] ASC,
    [Code] ASC
)
GO

可能有一个根记录,其中CodeType = 0,Code = 0,代表CodeType的类型。所有CodeType记录将具有CodeType = 0和Code> = 1。以下是一些示例数据,这些数据可能有助于澄清问题:

SELECT CodeType, Code, Description FROM Code

Results:

CodeType    Code    Description
--------    ----    -----------
0           0       Type
0           1       Gender
0           2       Hair Color
1           1       Male
1           2       Female
2           1       Blonde
2           2       Brunette
2           3       Redhead

可以将检查约束添加到Code表中,以确保在表中输入有效的CodeType:

ALTER TABLE [dbo].[Code] WITH CHECK ADD CONSTRAINT [CK_Code_CodeType]   
CHECK (([dbo].[IsValidCodeType]([CodeType])=(1)))
GO

函数IsValidCodeType可以这样定义:

CREATE FUNCTION [dbo].[IsValidCodeType]
(
    @Code INT
)
RETURNS BIT
AS
BEGIN
    DECLARE @Result BIT
    IF EXISTS(SELECT * FROM dbo.Code WHERE CodeType = 0 AND Code = @Code)
        SET @Result = 1
    ELSE
        SET @Result = 0
    RETURN @Result
END
GO

已经提出的一个问题是如何确保带有代码列的表对该代码类型具有正确的值。也可以通过使用函数的检查约束来强制执行此操作。

这是一个包含“性别”列的“人”表。最好的做法是用代码类型的描述(在本例中为Gender)命名所有代码列,并在其后加上单词Code:

CREATE TABLE [dbo].[Person](   
    [PersonID] [int] IDENTITY(1,1) NOT NULL,
    [LastName] [nvarchar](40) NULL,
    [FirstName] [nvarchar](40) NULL,
    [GenderCode] [int] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED ([PersonID] ASC)
GO

ALTER TABLE [dbo].[Person] WITH CHECK ADD CONSTRAINT [CK_Person_GenderCode] 
CHECK (([dbo].[IsValidCode]('Gender',[Gendercode])=(1)))
GO

IsValidCode可以这样定义:

CREATE FUNCTION [dbo].[IsValidCode]
(
    @CodeTypeDescription NVARCHAR(40),
    @Code INT
)
RETURNS BIT
AS
BEGIN
    DECLARE @CodeType INT
    DECLARE @Result BIT

    SELECT @CodeType = Code
    FROM dbo.Code
    WHERE CodeType = 0 AND CodeDescription = @CodeTypeDescription

    IF (@CodeType IS NULL)
    BEGIN
        SET @Result = 0
    END
    ELSE
    BEGiN
    IF EXISTS(SELECT * FROM dbo.Code WHERE CodeType = @CodeType AND Code = @Code)
        SET @Result = 1
    ELSE
        SET @Result = 0
    END

    RETURN @Result
END
GO

当查询具有代码列的表时,可以创建另一个函数来提供代码描述。这是一个 查询人员表的示例:

SELECT PersonID,
    LastName,
    FirstName,
    GetCodeDescription('Gender',GenderCode) AS Gender
FROM Person

这都是从防止数据库中查找表激增并提供一个查找表的角度来构思的。我不知道这种设计在实践中是否会表现良好。