NHibernate动态更新缺点?

时间:2012-12-19 14:49:27

标签: nhibernate nhibernate-mapping

有没有理由不对NHibernate使用dynamic-insert / dynamic-update?我问的唯一原因是它似乎是我想要启用的默认设置,而不是我必须配置的东西。

使用这些动态属性时是否有任何问题需要注意?

2 个答案:

答案 0 :(得分:26)

对于某些实体,您可以通过动态更新创建无效状态。假设您有Class Boolean属性A和逻辑依赖Integer属性B。如果属性ATrue,则属性B只能为负数,而如果属性AFalse,则为属性B只能是一个正数。

假设两个用户在给定的时间跨度内都与该类的实例进行交互。要开始,用户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更改为False并将B更改为125,并将其提交到数据库。现在我们遇到这种情况:

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都有有效状态,但数据库现在处于无效状态!用户查理出现并尝试实现此记录:

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的插入查询不会触发任何写入并抛出过时的数据异常(可以优雅地处理)。您还可以在数据库中编写类的逻辑要求,但是您必须小心谨慎,以确保数据库和程序在时间的推移下具有相同的编码要求,并且您将拥有多个位置在需求发生变化时进行更改,这并不总是值得开销。

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

答案 1 :(得分:6)

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

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

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