【问题标题】:What classes should I map against with NHibernate?我应该使用 NHibernate 映射哪些类?
【发布时间】:2010-06-05 03:44:57
【问题描述】:

目前,我们使用 NHibernate 将业务对象映射到数据库表。所述业务对象执行业务规则:如果违反该属性的合同,集合访问器将当场抛出异常。此外,属性强制与其他对象的关系(有时是双向的!)。好吧,每当 NHibernate 从数据库加载对象时(例如,当调用 ISession.Get(id) 时),映射属性的 set 访问器用于将数据放入对象中。

好处是应用程序的中间层强制执行业务逻辑。不好的是数据库没有。有时垃圾会进入数据库。如果垃圾被加载到应用程序中,它就会退出(抛出异常)。有时它显然应该放弃,因为它不能做任何事情,但如果它可以继续工作呢?例如,收集实时报告的管理工具运行不必要地失败的风险很高,而不是允许管理员甚至修复(潜在的)问题。

我现在没有示例,但在某些情况下,让 NHibernate 使用“前门”属性也会强制关系(尤其是双向)会导致错误。

什么是最好的解决方案?

目前,我将根据每个属性为 NHibernate 创建一个“后门”:

public virtual int Blah {get {return _Blah;} set {/*enforces BR's*/}}
protected virtual int _Blah {get {return blah;} set {blah = value;}}
private int blah;

我在 C# 2 中展示了上面的内容(没有默认属性)来演示这如何让我们基本上得到 3 层或视图,等等!虽然这确实可行,但它似乎并不理想,因为它要求 BL 为大型应用程序提供一个(公共)接口,并为数据访问层提供另一个(受保护)接口。

还有一个问题:据我所知,NHibernate 并没有给你一个方法来区分 BL 中的属性名称和实体模型中的属性名称(即查询时使用的名称) ,例如通过 HQL——只要你给 NHibernate 一个属性的名称(字符串)。这成为一个问题,首先,某些属性 Blah 的 BR 没有问题,因此您在 O/R 映射中引用它......但后来,您必须添加一些确实成为问题的 BR,所以那么您必须更改您的 O/R 映射以使用新的 _Blah 属性,该属性会破坏所有使用“Blah”的现有查询(针对字符串进行编程的常见问题)。

有没有人解决这些问题?!

【问题讨论】:

  • 不清楚为什么不能阻止无效数据进入数据库。我认为该场景没有通用的解决方法(无论是否涉及 NHibernate)。您可能会不断地轮询数据库以查找无效数据,然后在 NHibernate 尝试加载它之前尝试纠正它。
  • 刚找到相关讨论:stackoverflow.com/questions/129773/…
  • @Michael:好问题/评论。通常,它是一个旧版应用程序,其中预先存在的数据不符合业务要求(我知道我们应该清理它),或者另一个旧版应用程序允许不良数据进入。

标签: nhibernate business-logic business-rules


【解决方案1】:

虽然我发现您的大部分架构都有问题,但处理这些问题的常用方法是让 NHibernate 使用支持字段而不是 setter。

在上面的示例中,您不需要定义额外的受保护属性。只需在映射中使用它:

<property name="Blah" access="nosetter.lowercase"/>

这在文档http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-property 中有描述(表 5.1. 访问策略)

【讨论】:

  • 这实际上是 Hibernate 的首选访问策略:从数据库读取时不应强制执行业务规则,您应该只获取其中的内容。出于某种原因,NHibernate 的人不同意和提倡/推荐财产访问策略。
  • @Fried 这可能是因为 setter 通常不是使用 .NET/NHibernate 强制执行规则的地方。事实上,大多数持久化实体都使用自动属性,因此会生成 getter/setter 主体。
  • 感谢您的 cmets! @Diego,在我看来,这个解决方案会减少 C# 2 代码中对 Blah 的视图(只是属性和字段)。但是在 C# 3 中,它要求我有 2 层开头(属性和字段)——即,Blah 不能是默认属性;无论是否有任何业务逻辑要实现,都必须手动编码。我理解正确吗?
  • @apollodude 我不明白这个问题。这并不意味着在现有代码中有额外的层,因为您已经在使用非自动属性;您实际上是在删除一个层(受保护的属性)。
  • 很抱歉,不清楚。你的回答回答了我的问题。我说您的解决方案确实需要 2,而不是或多或少。澄清一下,它比上面的 C# 2 示例要少。但是,您的解决方案意味着我不能从默认属性开始(通过 C# 3)。我同意。我只是想确保我理解你。
猜你喜欢
  • 2017-06-06
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
相关资源
最近更新 更多