For some entities, you may create an invalid state though dynamic updates. Let's say you've got a Class
with a Boolean
Property A
and a logically dependent Integer
Property B
. If Property A
is True
, then Property B
can only be a negative number, while if Property A
is False
, then Property B
can only be a positive number.
Let's say that two users both interact with an instance of this class within a given time span. To start off, users Alice and Bob both materialize this class from the database, with the initial values of A
= True and B
= -50
Database Alice Bob
A: True A: True A: True
B: -50 B: -50 B: -50
VALID VALID VALID
User Alice changes A
to False
and B
to 125, and commits it to the database. Now we have this situation:
Database Alice Bob
A: False A: False A: True
B: 125 B: 125 B: -50
VALID VALID VALID
User Bob doesn't change A
, but changes B
to -75, then commits it to the database. If Dynamic updates are on, then NHibernate sees that Bob has only changed B
to -75, and issues a dynamic update that only edits the value of B
. If you had SQL validation on the server to prevent B
from being negative unless A
was true, you'd get a SQL error here, but let's say that you haven't reproduced all your business logic on your SQL tables. Here is the resulting data:
Database Alice Bob
A: False A: False A: True
B: -75 B: 125 B: -75
INVALID VALID VALID
Both Alice and Bob have valid states, but the Database is now in an invalid state! User Charlie comes along and tries to materialize this record:
Database Alice Bob Charlie
A: False A: False A: True A: False
B: -75 B: 125 B: -75 B: -75
INVALID VALID VALID INVALID
Charlie would likely get a validation error from your application when NHibernate tried to set the B property of the new instance of your class.
So, when you have logically dependent properties, you must have some strategy in place for avoiding this situation. One possibility is to simply enable select-before-update
for this entity. This can result in some additional database calls and a little slower performance. Another is to utilize versioning in NHibernate, which would mean that when Bob tries to save his record, NHibernate's insert query would not trigger any writes and throw a stale data exception (that can be gracefully handled). You also could codify the logical requirements of your class in the database, however you'll then have to be cautious to make sure the database and the program both have the same codified requirements as time goes on, and you'll have multiple places to make changes when requirements change, which isn't always a worthwhile overhead.
So in short, in many circumstances a developer must handle the details of dynamic-updates carefully, which is why it is not on by default. When you turn it on, consider if partial updates to your entity could cause problems, and if so, use one of the mitigating strategies I've recommended to protect against that issue.