This problem is driving me up the wall and I can't see any reason for
it. So help (or an admission that its a bug) would be helpful.
HNibernate 2.0.1GA with SQL Server 2005
I'm implementing what has become the defacto repository pattern in
that my domain layer has an interface that the repository (based on
NHibernate) implements. I'm using Microsoft Unity as my Service
Locator to load up the NHibernate enabled repository.
I have code such as this (which is a perfectly valid scenario in any
business I would think)
===>
IAsset newAsset = Factory.Create<IAsset>();
newAsset.Name = "New name";
IContent newContent = Factory.Create<IContent>();
newContent.Name = "New content";
IAssetContent newAssetContent = newAsset.AddContent(newContent);
newAssetContent.Quantity = 100;
repository.Add(newAsset);
repository.Add(newContent);
repository.Add(newAssetContent);
repository.Persist(); // All this does is a Session.Flush() wrapped
in a NHibernate transaction.
<==
This line: "repository.Add(newAsset);" fails with a "not-null
property references a null or transient value" on Content. I have
tried the following:
1) Move line to after the factory create of an asset. Result = Success
BUT NHibernate issues an INSERT for the Asset followed by an UPDATE
for the change of name. It works, but it's inefficent
2) Move "repository.Add(newContent);" to after IContent newContent =
Factory.Create<IContent>();. Result = Success, same SQL generated as
(1) though.
3) Move "repository.Add(newContent);" or "repository.Add
(newAssetContent);" to before the add of an Asset. Result = Fail, same
reason as described but missing value is Asset, not Content.
It appears that there are two (three?) problems here
1) The order objects are added to the repository actually makes a big
difference (I can't add a child before its parent) but assuming they
are all unsaved then this doesn't make sense - my "Persistent
Ignorant" domain later doesn't care how or when objects get created.
It just adds them to the repository (which is acting as my Unit of
Work) when it's done with them. When the persist takes place, that's
when all the magic happens and they get saved in order.
(see this post "Beginner: First insert of persistent entity Options"
and Thomas Krause comment that has not been answered as far as I can
tell: "NHibernate doesn't seem to reorder the inserts automatically.
Looking at the code it seems that there is some code in ActionQueue to
do this ordering, but it is commented out and I assume not finished in
the current version")
2) For some reason, I cannot just add them to the repository when I'm
done... I have to add them, then work on them (but only cases I cannot
fathom) though this creates SQL that is pointless. My domain layer
needs to be careful what gets added when - this seems to be such a
flakey situation that adding something new to the object model could
cause a break that won't be easy to track down.
3) INSERTS and UPDATES are issued when not neccessary
I've read the argument is that you have saved an object to NHibernate,
it creates the need for an Insert..... then the update comes along and
NHibernate is being fantastic by working out a change has occured. Ok,
fair enough - but I haven't actually Persisted them yet. I've only
added them to my Unit Of Work (i.e. the Session). NHibernate should be
smart enough to know that it has never saved this to the DB, been
subsequently changed, but it isn't actually saved to the DB so it can
combine the Insert and Update together.
I know that's what the empty ID option is for and by doing the
Session.Save() it overwrites this so that is why I tried to stack my
add's up until I was ready...but the crash mentioned above prevents me
doing that.
So I'm basically stuck.
Mapping files for interest:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
namespace="Domain.SupplyChain"
assembly="Domain.SupplyChain"
default-access="field.camelcase-underscore"
default-lazy="true">
<class name="Asset"
proxy="Domain.SupplyChain.Interfaces.IAsset,
Domain.SupplyChain.Interfaces"
table="Asset">
<id name="Id" column="Id" unsaved-
value="00000000-0000-0000-0000-000000000000" access="property">
<generator class="guid.comb" />
</id>
<property name="Name" type="string" length="255" not-null="true" /
>
<bag name="AssetContents" table="AssetContents" inverse="true"
cascade="all" >
<key column="AssetId" />
<one-to-many class="AssetContent" />
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
namespace="Domain.SupplyChain"
assembly="Domain.SupplyChain"
default-access="field.camelcase-underscore"
default-lazy="true">
<class name="Content"
proxy="Domain.SupplyChain.Interfaces.IContent,
Domain.SupplyChain.Interfaces"
table="Content">
<id name="Id" column="Id" unsaved-
value="00000000-0000-0000-0000-000000000000" access="property">
<generator class="guid.comb" />
</id>
<property name="Name" type="string" length="255" not-null="true" /
>
<bag name="AssetContents" table="AssetContents" inverse="true"
cascade="all" >
<key column="ContentId" />
<one-to-many class="AssetContent" />
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
namespace="Domain.SupplyChain"
assembly="Domain.SupplyChain"
default-access="field.camelcase-underscore"
default-lazy="true">
<class name="AssetContent"
proxy="Domain.SupplyChain.Interfaces.IAssetContent,
Domain.SupplyChain.Interfaces"
table="AssetContent">
<id name="Id" column="Id" unsaved-
value="00000000-0000-0000-0000-000000000000" access="property">
<generator class="guid.comb" />
</id>
<many-to-one name="Asset" column="AssetId" class="Asset" not-
null="true" />
<many-to-one name="Content" column="ContentId" class="Content" not-
null="true" />
<property name="Quantity" type="int" not-null="true" />
</class>
</hibernate-mapping>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---