【问题标题】:Why should a C# property getter not read from a DB?为什么不应该从数据库中读取 C# 属性获取器?
【发布时间】:2011-07-13 17:16:37
【问题描述】:

这个问题的一些答案和 cmets:Simplest C# code to poll a property?,暗示在属性的 getter 中从数据库中检索数据通常是一个坏主意。
为什么这么糟糕?

(如果您有信息来源,请注明。)


如果这会影响您的回答,我通常会在第一次“获取”之后将信息存储在一个变量中以供重复使用。

【问题讨论】:

  • 由于 getter 的目的是反映对象的当前状态,此时从数据库中检索值是不合适的操作。对象实例化或查找是访问数据库的正确时间。然后,getter 可以返回读取的值。
  • @KevinDTimm 但是如果我不知道在初始化时是否需要数据库中的数据怎么办?

标签: c# properties


【解决方案1】:

因为从数据库中检索数据可能会导致任意数量的异常,而属性 getter 通常不应该抛出异常。

属性 getter 的预期行为只是返回一个值;如果它实际上做了更多的事情,它应该是一种方法。

Microsoft 的 Property Design 指南解释了原因: https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/property

【讨论】:

  • 好吧,为什么他们不应该抛出异常?
  • 他们不应该抛出异常的一个原因是因为属性可以是 UI 中数据绑定的一部分。不过,我敢肯定还有很多其他原因。
  • 它们不应该抛出异常,因为它们通常不应该首先包含逻辑。
  • 因为 getter 的工作通常是返回一个存储的值……而不是执行一堆逻辑。在 .NET 中,库的用户不会期望属性引发异常。
  • @Protector:您正在深入研究最佳实践的各个方面,这些方面在 MSDN 中的记录方式与语言语法和对象命名空间不同。你可能会在这里找到一些东西:stackoverflow.com/questions/1529604/c-antipatterns
【解决方案2】:

这很糟糕,因为(除其他外)它违反了Principle of Least Astonishment

程序员通常希望属性执行简单的获取/设置。将数据访问封装在一个属性中,这可能会引发异常、导致副作用并改变数据库中数据的状态,这不是通常所期望的。

我并不是说没有复杂属性的情况 - 有时,它可能是一个很好的解决方案。但是,这不是预期的做事方式。

【讨论】:

    【解决方案3】:

    简短版:让属性 getter 直接访问数据库会违反 Separation of Concerns 原则。

    更多详情: 一般来说,属性旨在表示与对象关联的数据,例如Person 对象的FirstName 属性。属性值可以在内部或外部设置,但修改和检索对象上的此数据的行为应该与检索或提交该数据到永久存储的行为分开。

    【讨论】:

      【解决方案4】:

      每当您访问 getter 时,您都会再次调用您的数据库。

      【讨论】:

      • 如果我在第一次得到答案后存储答案,在类似单例模​​式的场景中?
      • 那么为什么不创建一个从数据库中填充类的方法呢?那么这个类本身就完全不用担心你的数据库了。
      • 然后您应该将逻辑移动到类中的私有方法中,并将数据存储在您的 getter 提供访问权限的私有字段中。逻辑不需要在属性本身中。
      • +1 我们遇到过类似的情况,在 .OrderByDescending(o => o.PropertyThatDoesMoreThanYouThink) 方法中对数百个对象的集合使用了此类属性。开发人员对此属性进行了排序,而从未假设此属性访问数据库。当然,这是后来修复的,因为它会导致数百次不必要的数据库查询和性能问题。
      【解决方案5】:

      根据定义,getter 应该只是封装数据,而不是功能。

      此外,如果您有多个 getter 需要往返数据库,您可能会重新定义功能并多次访问数据库。为什么不集中处理,而不是将其拆分到多个属性中?

      方法用于类级别的数据修改和功能,属性仅用于单独的数据修改和检索。

      【讨论】:

        【解决方案6】:

        除了可能出现的异常之外,查询数据库是一个缓慢的操作。在这两个方面,使用属性获取器作为数据库访问器违反了principle of least astonishment 客户端代码。如果我看到一个带有属性的库类,我不希望它做很多工作,而是访问一个易于检索的值。

        这里最不令人惊讶的选择是提供一个老式的、简单的 Get 函数。

        【讨论】:

          【解决方案7】:

          如果您确实只是从数据库中检索值而不将其值写回,例如只读属性,则本质上没有任何错误。特别是如果该属性不能没有其父级而存在。然而,在实施过程中,它可能会导致可维护性问题。您正在将检索存储信息的过程与对该信息的访问相结合。如果您继续遵循这种模式来处理其他属性,并且存储系统的各个方面发生变化,那么这种变化可能会在您的代码库中激增。例如表名或列数据类型更改。这就是为什么在你的属性 getter 中调用数据库是不好的。

          附带说明:如果数据库在您尝试检索值时抛出异常,那么显然您的代码(或调用客户端的代码)中存在错误,并且无论您将数据访问代码。很多时候,数据是由类中可能引发异常的某种集合支持的,以这种方式存储属性值是标准做法(请参阅EventHandlerList)。

          属性是专门设计的,因为程序员需要在获取和设置值时执行额外的逻辑,例如验证。

          说完所有这些,重新检查您的代码并问自己“以后更改它有多容易?”从那里你应该正在寻找更易于维护的解决方案。

          【讨论】:

            猜你喜欢
            • 2019-09-15
            • 1970-01-01
            • 1970-01-01
            • 2017-06-02
            • 2021-11-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多