On Thu, Jul 17, 2008 at 1:38 AM, Paul Batum <paul....@gmail.com> wrote:
> Firstly, is this the expected behaviour?
This is standard NH behaviour. NH uses a UnitOfWork pattern - so
calling save only marks an object for persistence. It wont
(automatically) save the object to the DB. For objects which are
mapped as Identity - NH does execute an insert automatically - but
this is for the obvious reason of obtaining an PK.
Session (UoW) flushes happen when necessary - e.g. before a read so
that read data isn't stale - but in general - you need to manage the
duration of the Session (UoW) yourself - or call flush.
> Secondly, has anyone had to work around this problem? Do you put in
> explicit flush calls before you perform an action that will require
> appropriate ID's to be assigned (such as serialization to DTO's)?
Most people (AFAIK) use some abstraction on top of ISession so that
they can use something like:
using(UnitOfWork.Begin()) {
obj.Save();
other.Delete();
}
There are a number of these around.
> Thirdly, is this problem usually avoided by using a different ID
> generation algorithm, such as HiLo? Can anyone comment on the
> different id generation algorithms? Do most people avoid using
> SQLServer identity columns as the primary key?
Depends on your specific situation. HiLo has it's own problems
(generating IDs outside of NH - if you happen to need to do ETL or
share the DB for some reason).
You should also be aware that NH can and will save modified entities
without any call save if it detects they're dirty during a session
flush.
e.g.
var myentity = session.Get(1);
myentity.Name = "some new name";
....
// some other action causes a session.Flush(); could be a query or Get
- writes the changed myentity to the DB!
...
This is because during a flush NH compares the state of any entities
in it's UoW with the dehydrated (i.e. row/column) state that it pulled
from the DB. If it notices that things have changed then it will
automatically write these changes back.
j.
When working with domain objects that have a SQLServer integer identity column for their primary key, when I call save on a transient object, the insert statement is triggered -immediately-.
Hi Paul,
the behavior you describe seems inconsistent to me. I have verified it right now and I don't understand why NH goes to the DB for the parent while it doesn't for the child. Have you had the chance to investigate it further?
But you didn't explain why it does it when persisting transient root objects but not for child transient objects of parent persistent objects.
Yes, no big deal for me too, but I still can't get why for the parent object it goes to the db to get the id while for the child it doesn't.
P.S. Was the last chance.
I'm sorry Fabio but I could not follow the point you were trying to
make there. The question that Simone was eluding to is why cascades
only occur on flush.
I suspect to get a real answer we would have to
ask the hibernate designers?
Please Fabio, there is no need to be rude.
Are there any good resources that explain the
differences?
I can only *save* a transient object, it is *unsaved* prior to the call.
When I have a persistent object, it is already *saved*, so *save* does nothing.
When there are changes, all changes will be *flushed* or *persisted*
when the UnitOfWork is completed.
In this spirit, I call save or evict to toggle between transient and
persisted state, but I don't notifiy NH of changes to persistent or
transient entities.
-Markus
Can you tell me why test 1 passes but test 2 fails? Assume wrapped in
a transaction...
[Test]
public void ExpectCascadeOnTransient()
{
var message = new Message { Content = "Ciao" };
message.Receiver = new Contact { Name = "Simone" };session.Save(message);
Assert.That(message.Receiver.ID, Is.GreaterThan(0)); //
Passes OK
}
[Test]
public void ExpectCascadeOnPersistent()
{
var message = new Message { Content = "Ciao" };
session.Save(message);
message.Receiver = new Contact { Name = "Simone" };session.Save(message);
Assert.That(message.Receiver.ID, Is.GreaterThan(0)); //
FAILS
}
-Markus
-Markus
-Markus
On 7/30/08, Paul Batum <paul....@gmail.com> wrote:
>
I think I must have got some of my terminology confused. Based on what
Markus and Ayende said:
var p = new Person() // p is transient
session.Save(p) // p is persistent
session.Evict(p) // p is transient
What terminology do you use to differentiate between the state of p at
line one and at line three?
new Person { Id = 5 }; <== how do you define this?
new Person { Id = 5 }; <== how do you define this?
The question is: Is there any "official" state model about NH object
states? I am currently writing docs on Castle ActiveRecord and started
an article about the persistant object lifecycle. ISession says there
only two states: transient and persistant. However, there is also a
StaleObjectStateException, so there must be at least the third state
of stale. I identified some more, but hitherto couldn't back them up
by the NH source. Perhaps someone has a hint where to look in the
sources for it.
-Markus
As a rule of thumb, just don't use native PKs. Then you will have no
db activity besides flushes.
-Markus