NHibernate动态更新缺点?

NHibernate动态更新缺点?,nhibernate,nhibernate-mapping,Nhibernate,Nhibernate Mapping,是否有理由不为NHibernate使用动态插入/动态更新?我问这个问题的唯一原因是,它似乎是我希望作为默认值启用的东西,而不是我必须配置的东西 在使用这些动态属性时,是否有需要注意的问题?对于某些实体,您可能会通过动态更新创建无效状态。假设你有一个类,它有一个布尔属性a和一个逻辑相关的整数属性B。如果属性A为True,则属性B只能是负数,而如果属性A为False,则属性B只能是正数 假设两个用户都在给定的时间跨度内与该类的一个实例交互。首先,用户Alice和Bob都从数据库中具体化这个类,初始值

是否有理由不为NHibernate使用
动态插入
/
动态更新
?我问这个问题的唯一原因是,它似乎是我希望作为默认值启用的东西,而不是我必须配置的东西


在使用这些动态属性时,是否有需要注意的问题?

对于某些实体,您可能会通过动态更新创建无效状态。假设你有一个
,它有一个
布尔属性
a
和一个逻辑相关的
整数
属性
B
。如果属性
A
True
,则属性
B
只能是负数,而如果属性
A
False
,则属性
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都具有有效状态,但数据库现在处于无效状态!用户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可能会从应用程序中得到验证错误

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


因此,简而言之,在许多情况下,开发人员必须仔细处理动态更新的细节,这就是为什么它在默认情况下不启用的原因。当您打开它时,请考虑是否对您的实体进行部分更新可能会导致问题,如果是这样的话,请使用我建议的一个减轻策略来保护该问题。 动态插入和更新有轻微的性能成本,因为NHibernate每次都必须构造SQL,而不是缓存SQL。我不知道数据库方面是否有成本。动态插入和更新对于故障排除和分析非常方便。如果我能够测量一个有意义的性能冲击,我会在开发中打开它,在生产中关闭它

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


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

非常有用。我甚至不知道更新前选择。在本例中,应用程序允许用户在实体处于无效状态时提交更改。该类应封装对这些属性的访问,以便强制执行业务规则,和/或在提交事务之前验证实体。我不认为这与动态更新有任何关系。我确实没有抓住要点,如果可以的话,我会收回我的否决票(作为补偿,我对你其他一些优秀的答案投了更高的票)。对不起,我读了不止两遍,仍然没有抓住要点。看来版本控制可能是一个很好的解决方案。更新前选择破坏了动态更新的所有优点,以及乐观lock=“all”,因为数据库必须首先读取整行并比较值,这对于长字符串/varchar和clob/varchar(max)对象尤其不好。我认为至少应该在数据库级别通过检查约束强制执行此规则,如果这很重要的话。但是,我认为在保存之前必须在实体级别对其进行验证,因为如果知道它不是有效状态,它甚至不必在找到它之前访问数据库。当我查看使用log4net生成的SQL时,它似乎仍然使用参数化查询。这些东西不是还会被缓存在线路的某个地方吗?另外,关闭动态查询不也会因为更新未更改的字段而影响性能吗?或者,这一成本可以忽略不计?感谢您的反馈。NHibernate可以缓存静态查询格式,因此创建查询只是填补空白。对于动态查询,每次都必须构造查询。更新所有字段(如果有)的性能影响取决于数据库。有很多因素,但我的观点和经验使我建议使用动态插入和更新。