【问题标题】:DAL. Modelling data constraints best practice达尔。建模数据约束最佳实践
【发布时间】:2011-04-02 04:44:34
【问题描述】:

存储在具有数据约束的关系数据库中的数据(例如最大字符串属性长度)。客户端使用数据访问库(DAL)以ORM方式管理数据(存储库+数据域类)

您个人会在哪里实施约束? 例如:

数据域类:

class Person
{
 private string _name;
 public string Name 
 {
   get { return _name; }
   set { _name = StringHelper.Truncate(value, 50) }
 }
 ...
}

或者可能是存储库:

PersonRepository {
  public void CreatePerson(Person p) {
    p.Name = StringHelper.Truncate(p.Name, 50);
    ... 
    DataContext.Insert(..);
  }
}

或者您可能应该使用分配给数据域类属性的属性,这些属性将通过反射在存储库方法中处理,以自动截断字符串字段。

class Person {
   [StringConstraint(MaxLength = 50)]
   public string Name { get; set; }
} 

PersonRepository::CreatePerson(p) {
  EntityHelper.ApplyConstraints(p);
  ...
}

或者可能是别的什么?

提前感谢您!

【问题讨论】:

    标签: .net orm data-access-layer


    【解决方案1】:

    我会在业务逻辑层使用与数据库相关类不同的业务逻辑类。我不会冒泡 sql 错误,甚至不会在数据库中强制执行它。在我看来,数据库应该只关心数据的形状和一致性。与实际数据本身无关。

    关于 50 个字符的规则是业务规则,而不是逻辑、关系或“结构”规则。它可以很容易地是 51 个字符或 49 个字符。您随意选择了 50 个,这很好。这就是业务层对象的用途。执行这些规则。

    任何对您数据的业务访问,都应该再次通过业务层,通过服务、直接引用或您选择的其他方法公开。

    对数据库的唯一“直接”访问再次应该是关心数据的形状和一致性的事情,而不是实际数据本身。诸如备份、复制、集群、负载平衡、审计等。

    所以 ORM 类只是 Person 的业务对象和 Person 在实际数据库中的存储之间的粘合剂。数据库应该只关心数据库的整体形状和结构以及实际数据存储的底层基础设施和机制。业务对象应该确定对象的“性质”并定义它的真正含义。一个人至少应该有一个名字,他们的年龄不能超过 110 岁,他们的身高不能超过 7 英尺,等等。

    这就是我的哲学/经验法则:-)

    【讨论】:

    • 所以现在当长度发生变化时,需要更新两个地方——数据库,业务层...
    • 这就是为什么我说我什至不会费心将验证放入数据库中。数据库不应该只看数据本身的逻辑结构,即一个人可以与许多订单和底层基础设施相关联。更新人员触发器并进入另一个表。关于“集中以防有人具有备用访问权限”,请参阅我关于通过 BL 层进行业务与直接访问数据库操作的段落
    【解决方案2】:

    约束是验证的一部分。验证对象是业务层的责任,但在 UI 中使用相同的验证逻辑也很方便。共享此类逻辑的方法是使用一些 API,这些 API 使用验证属性标记您的数据对象。您可以在 BL 和 UI 中运行相同的验证。 DataAnnotations 提供了这个功能,它也可以通过验证应用程序块来实现。

    编辑:这并不意味着您不会在数据库中放置约束。这仅意味着您应该能够尽快检测到约束违规以保存到数据库的往返行程。

    【讨论】:

    • 您个人会将 DataAnnotation 属性放在哪里?要“数据域”类还是制作另一层类?
    • 这是基于您的应用程序的复杂性一个假定的设计。如果您使用在所有层之间共享的简单对象,这种方法效果最好。如果您为每个层使用不同的对象集,则必须对每个集重复验证(例如:对未暴露给 UI 的域对象进行验证,对暴露给 UI 的 DTO 对象进行另一个验证)。
    【解决方案3】:

    在数据库中是我的偏好。
    如果有人尝试插入过长的字符串,则会返回 SQL 错误。由应用程序通过向用户显示有用的消息来处理该错误。

    它也是集中式的,以防有人拥有备用访问权限 - SSMS 或其他应用程序代码。

    【讨论】:

    • 我有 UI 来操作数据并且我想拒绝用户输入太长的字符串。如果程序告诉他们“发生了 Sql 错误”,那将是不正常的,因此应该以某种方式将数据约束转换为 UI。
    • 你不会告诉用户 SQL 错误; SQL 错误将被应用程序捕获,应用程序将显示字符串太长的消息。是“由应用程序通过向用户显示有用的消息来处理该错误。”这么难懂?!
    • 我明白了,但是拒绝输入冗长的字符串而不是耗时的 ui-dbms 往返以及任何类型的错误消息(“嘿!你的名字太长了!请,删除 10 个字符") 。在我看来,约束应该从 dbms 级别开始。
    • @Andrew Florko:这意味着不止一个地方拥有该长度/等值 - 您已经创建了一个需要同步才能具有任何值的冗余。
    • 是的,没错。但是发展舒适度(集中约束)对客户没有价值。他们应该有响应式、智能的用户界面。
    猜你喜欢
    • 2010-12-10
    • 2017-03-03
    • 2019-10-22
    • 2014-10-03
    • 2019-04-17
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多