16

是否有理由不使用dynamic-insert/dynamic-update用于 NHibernate?我问的唯一原因是它似乎是我希望将其作为默认启用的东西,而不是我必须配置的东西。

使用这些动态属性时有什么需要注意的问题吗?

4

2 回答 2

35

对于某些实体,您可能会通过动态更新创建无效状态。假设您有一个Class带有属性的Boolean属性A和一个逻辑依赖的Integer属性B。如果 PropertyATrue,那么 PropertyB只能是负数,如果 PropertyAFalse,那么 PropertyB只能是正数。

假设两个用户都在给定的时间跨度内与此类的一个实例进行交互。首先,用户 Alice 和 Bob 都从数据库中实现了这个类,初始值为A= True 和B= -50

Database   Alice       Bob
A: True    A: True     A: True
B: -50     B: -50      B: -50
VALID      VALID       VALID

用户 Alice 更改A为125FalseB125,并将其提交到数据库。现在我们有这种情况:

Database   Alice       Bob
A: False   A: False    A: True
B: 125     B: 125      B: -50
VALID      VALID       VALID

用户 Bob 没有更改A,而是更改B为 -75,然后将其提交到数据库。如果动态更新开启,NHibernate 会看到 Bob 仅更改B为 -75,并发出仅编辑 的值的动态更新B。如果您在服务器上进行了 SQL 验证以防止B出现负数,除非A为真,那么您会在此处收到 SQL 错误,但假设您尚未在 SQL 表上重现所有业务逻辑。这是结果数据:

Database   Alice       Bob
A: False   A: False    A: True
B: -75     B: 125      B: -75
INVALID    VALID       VALID

Alice 和 Bob 都有有效的状态,但数据库现在处于无效状态!用户 Charlie 出现并尝试实现此记录:

Database   Alice       Bob       Charlie
A: False   A: False    A: True   A: False
B: -75     B: 125      B: -75    B: -75 
INVALID    VALID       VALID     INVALID

当 NHibernate 尝试设置类的新实例的 B 属性时,Charlie 可能会从您的应用程序中收到验证错误。

因此,当您具有逻辑相关属性时,您必须制定一些策略来避免这种情况。一种可能性是简单地启用select-before-update该实体。这可能会导致一些额外的数据库调用和稍慢的性能。另一个是在 NHibernate 中使用版本控制,这意味着当 Bob 尝试保存他的记录时,NHibernate 的插入查询不会触发任何写入并抛出过时数据异常(可以优雅地处理)。您也可以在数据库中编写类的逻辑要求,但是您必须谨慎确保数据库和程序随着时间的推移都具有相同的编码要求,并且您将有多个地方当需求发生变化时进行更改,这并不总是值得的开销。

所以简而言之,在许多情况下,开发人员必须仔细处理动态更新的细节,这就是默认情况下不启用的原因。打开它时,请考虑对实体的部分更新是否会导致问题,如果是,请使用我推荐的一种缓解策略来防止该问题。

于 2012-12-19T15:11:08.513 回答
6

动态插入和更新有轻微的性能成本,因为 NHibernate 每次都必须构造 SQL 而不是缓存它。我不知道数据库方面是否有成本。动态插入和更新对于故障排除和分析非常方便。如果我能够衡量一个有意义的性能影响,我会在开发中打开它并在生产中关闭它。

您可能会遇到侦听器和拦截器的问题,请参阅此问题

我在我的 NHibernate 应用程序中打开了它,没有任何问题。我的回答是否定的,没有充分的理由不使用它。

于 2012-12-19T15:38:30.690 回答