繁体   English   中英

在.NET中存储业务值的位置 - SQL Server应用程序

[英]Where to store business values in .NET - SQL Server applications

这一直是开发人员的鸡和蛋问题。 您在哪里存储应用程序规则中使用的业务值。 (在ASP.NET,Window Forms或任何数据驱动的应用程序中)

我见过人们在创建表格时会存储文本和值表示,然后将这些记录链接到代码中(通过ID或文本名称)。 对我而言,这是最糟糕的方式:

  • 你必须维护表并为每个创建管理模块
  • 您每次需要访问业务价值时都已阅读该表
  • 如果没有预先填充数据库,您的应用程序将无法运行 -

大多数开发人员告诉我这是我不买的“最佳实践”,因为它没有带来任何好处,我把业务价值直接放到这样的应用程序:

public enum SourceLocation
        {
            Database = 0,
            File = 1,
            UserInput = 3        
        }

然后在[Column]上使用来自/到数据库的整数,它直接在数据对象上转换为Enum,因此逻辑可以直接说:

if(DataObject.Column == SourceLocation.File)
       //Read From File

这解决了上述所有问题,但是当您在应用程序之外运行数据库报表时,您需要在SQL中对这些值进行转换。

所以我仍然想知道开发人员是否还有其他“更好”的解决方案或模式。 我的意思是每个数据驱动的应用程序必须有一个方法/设计来解决这个问题,这个问题从一开始就存在。

我不太确定我同意你的看法,将这些值存储在枚举中可以为你提供将它们存储在某种外部数据源中的所有好处。

你必须维护表并为每个创建管理模块

确实,将值存储在外部数据源中会增加一些架构开销。 但是,如果您使用任何类型的ORM来处理数据访问和代码生成,这是一个非常小的尝试。

我不确定你的“管理模块”是什么意思,但我会假设你的意思是一个存储库,而不是一些用户自己管理选项的界面。 如果备选方案将值放在枚举中,我不明白为什么后者是必需的,因为用户也无法管理它们。

就“维护”表而言,除了从枚举中添加或删除值之外,您实际上不需要进行任何维护。 正如JonH所指出的,枚举路由要求您重建和重新部署整个应用程序,而不是简单地在数据源中添加或删除行。 对我来说,这是一个更大的维护负担。

您每次需要访问业务价值时都已阅读该表

事实并非如此,因为我假设这些值是相当静态的,所以在应用程序启动时缓存这些值并完成它是非常简单的。

如果没有预先填充数据库,您的应用程序将无法运行

所以呢? 如果应用程序是数据驱动的,则需要部署和配置数据库是部署计划的一部分。 在脚本中添加2或3个INSERT语句会增加部署过程的复杂性吗?

这解决了上述所有问题,但是当您在应用程序之外运行数据库报表时,您需要在SQL中对这些值进行转换。

最重要的是,这是所有人在外部存储这些值的最有说服力的理由。 鉴于报告中使用这些值的事实意味着它们的含义超出了您的应用范围 这意味着当他们需要在其他地方使用时,您每次都必须复制这些知识。 系统中的任何重复都会产生额外的维护负担,并增加在将来的更新中引入错误的机会。

最后,Enums在向UI元素进行数据绑定时往往更加困难。 如果可以,他们不允许向用户显示“漂亮”的值名称。 相反,它们会显示下拉框,其中包含“UserStoredFile”和“PickAndChooseAnotherEnumValue”等项目。 除了将枚举值与单独的字符串相关联(更多重复,请参阅上面的段落)之外,没有办法克服Enums的这种限制。

虽然看起来没什么大不了的,但任何体面的开发者都应该关心这样的小细节。 关注整个用户体验非常重要。 有可能,如果你不是特别注重细节,你的系统中可能还有很多其他地方也会出现问题。 不可否认,最后一点更像是主观的肥皂盒类型的论点:)。

我同意你的观点,只存储这些值并不能证明在应用程序中添加数据库是不合理的。 但是,您会注意到我通常会说外部数据源 您无法设置应用程序从XML或其他类型的外部配置文件中提取这些值。 但是,如果您已经拥有数据库,那么您可以将它们保存在一个地方。

编辑:

使用这些对象非常简单,它们只是集合。 它们比枚举更自然地数据绑定,我想在数据驱动的应用程序中这很重要:

// Bind a collection of SourceLocation to an ASP.net dropdown list
ddlSourceLocations.Datasource = GetSourceLocations();
ddlSourceLocations.DataTextField = "LocationName";
ddlSourceLocations.DataValueField = "LocationId";
ddlSourceLocations.DataBind();

当然,就像你提到的那样,枚举肯定不是不可能的,它通常不那么好。

如果SourceLocation的概念需要超越名称和ID,那么通过枚举将这些“业务价值”转化为完整的对象也可以为未来提供更大的灵活性。

让我们假设稍后将“IsRemote”属性添加到SourceLocation,以表示该位置驻留在单独的计算机上。 SourceLocation现在能够容纳需要此属性的规则:

if(myDataObject.SourceLocation.IsRemote) {
    // If the location is remote, do something extra   
}

如果您的某些代码需要IsRemote为true的所有位置,您还可以通过此属性过滤SourceLocation集合:

var remoteLocations = GetSourceLocations().Where(x => x.IsRemote);

但是,在一个方面,枚举确实比数据驱动对象具有明显的优势,那就是它们被用作应用程序常量。 事实上,这就是一个真正的枚举,一组常数。 当将规则实现为动态的,数据驱动的规则时,更有效地针对静态值编写规则。

在您的具体示例的情况下,这是真的。 您的所有规则都是“如果源位置== 1,那么就这样做”。 我永远不会想要在我的应用程序中浮动一堆魔术,所以我肯定会定义一个类似你上面的枚举。

这是否意味着在这种情况下我只使用枚举并放弃在外部数据源中保存值? 不一定,这一切都取决于在系统环境中如何使用特定值。 在您的示例中,这些值似乎在整个域中具有重要性,而不仅仅是单个应用程序。 您已将它们描述为“业务价值”,并提到它们用于其他应用程序,例如报告。 对我来说,这将使得提供一个可以共享这些知识的中心位置是完全合适的,除了在枚举中定义它们之外,我会坚持它们。

你可能会说,“等等......不是重复吗?不是那么糟糕吗?” 是的,但不会少于你使用仅枚举路线,你仍然可以获得设计业务价值的设计奖金作为完整的域对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM