NHibernate动态更新缺点?
是否有理由不为NHibernate使用NHibernate动态更新缺点?,nhibernate,nhibernate-mapping,Nhibernate,Nhibernate Mapping,是否有理由不为NHibernate使用动态插入/动态更新?我问这个问题的唯一原因是,它似乎是我希望作为默认值启用的东西,而不是我必须配置的东西 在使用这些动态属性时,是否有需要注意的问题?对于某些实体,您可能会通过动态更新创建无效状态。假设你有一个类,它有一个布尔属性a和一个逻辑相关的整数属性B。如果属性A为True,则属性B只能是负数,而如果属性A为False,则属性B只能是正数 假设两个用户都在给定的时间跨度内与该类的一个实例交互。首先,用户Alice和Bob都从数据库中具体化这个类,初始值
动态插入
/动态更新
?我问这个问题的唯一原因是,它似乎是我希望作为默认值启用的东西,而不是我必须配置的东西
在使用这些动态属性时,是否有需要注意的问题?对于某些实体,您可能会通过动态更新创建无效状态。假设你有一个
类
,它有一个布尔属性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可以缓存静态查询格式,因此创建查询只是填补空白。对于动态查询,每次都必须构造查询。更新所有字段(如果有)的性能影响取决于数据库。有很多因素,但我的观点和经验使我建议使用动态插入和更新。