NHibernate: Make sure that the foreign key is not null - nhibernate

Is there anyway to make sure that when I export schema in NHibernate, I can make sure some of the columns must not be null?
For example, in the below case, the column Doc_ID in ReuploadTable must not be null:
<class name="Test.Generated.BusinessObjects.DocumentStore, DAL" table="document_store" lazy="true">
<id name="Id" column="Id">
<generator class="native" />
</id>
<bag name="ReuploadTables" lazy="true" cascade="all-delete-orphan" inverse="true" >
<key column="Doc_ID"></key>
<one-to-many class="ReuploadTable"></one-to-many>
</bag>
</class>
<class name="Test.Generated.BusinessObjects.ReuploadTable, DAL" table="reupload_table" lazy="true">
<id name="Id" column="ID">
<generator class="native" />
</id>
<property name="ReuploadTimes" column="ReuploadTimes" />
<property name="FilePath" column="FilePath" />
<many-to-one name="DocumentStore" column="Doc_ID" class="DocumentStore" />
</class>
And this is how I do the insertion:

Probably you can try to set
<key column="Doc_ID" not-null="true"></key>

Related

NHibernate removing FK in one-to-many association on update

First, here is my relation
<class name="ServiceStep">
<id name="Id">
<generator class="guid.comb"/>
</id>
<set name="AdditionalInfoRows" cascade="save-update" >
<key column="ServiceStepId"/>
<one-to-many class="AdditionalInfoRow"/>
</set>
<class name="AdditionalInfoRow">
<id name="Id">
<generator class="guid.comb"/>
</id>
<set name="AdditionalInfos" cascade="save-update" >
<key column="AdditionInfoRowId"/>
<one-to-many class="AdditionalInfo"/>
</set>
Now, when I create new ServiceStep and add AdditionalInfoRows into it, everything works fine and it's correctly persisted.
The problem is by update. I load ServiceStep and the Set is correctly loaded with AdditionalInfoRows. In my application I add new AdditionalInfoRows to this set. Then I call SaveOrUpdate on ServiceStep. Newly addes AdditionalInfoRows are persisted correctly but my original list looses the connection. FK in AdditionalInfoRows which should point to ServiceStep is set to NULL by NHibernate.
Hope somebody can point me into right direction.
You can try including something like this in your AdditionalInfoRow mapping:
<many-to-one name="ServiceStep" class="ServiceStep">
<column name="ServiceStepId" not-null="true"/>
</many-to-one>
to look like,
<class name="AdditionalInfoRow">
<id name="Id">
<generator class="guid.comb"/>
</id>
<set name="AdditionalInfos" cascade="save-update" >
<key column="AdditionInfoRowId"/>
<one-to-many class="AdditionalInfo"/>
</set>
<many-to-one name="ServiceStep" class="ServiceStep">
<column name="ServiceStepId" not-null="true"/>
</many-to-one>
</class>

nhibernate : mapping to column other than primary key

I have the following map. My intention is for the order.BasketId to map to orderItem.BasketId. Tho when i look at the sql i see that it's mapping
order.Id to orderItem.BasketId. How do i define in my order map which order property to map against basketId. It seems to default to the primary key.
<class name="Order" table="Orders">
<id name="Id" type="Int32" column="Order_ID" unsaved-value="0">
<generator class="identity"/>
</id>
<property name="BasketId" column="Basket_ID" type="Int32"/>
<set name="OrderItems" table="item_basket_contents" generic="true" inverse="true" >
<key column="Basket_ID" />
<one-to-many class="EStore.Domain.Model.OrderItem, EStore.Domain"/>
</set>
</class>
and orderItem
<class name="OrderItem" table="Item_Basket_Contents">
<id name="Id" type="Int32" column="ID" unsaved-value="0">
<generator class="identity"/>
</id>
<property name="BasketId" column="Basket_ID" type="Int32"/>
</class>
Use the following:
<key column="Basket_ID" property-ref="BasketId" />
That's it.
Can you change the structure? I would have a Basket entity, which contains the order items. Your order then refers to this basket, and the basket contains the items. The explicit basketID in Order is circumventing some of the ORM that hibernate does.

How do I map a one-to-many relationship through a join table?

How would I go about mapping the following in NHibernate?
My entities and ERD are below. I know how to map a many-many relationship, but dont know how to map the joining table ReportTargets to the Datapoint table. You will notice that there is no ReportTargets entity model as it is not strictly a domain entity. What is the best solution here? I am a NHibernate newbie so go easy please..:) Thanks
http://img341.imageshack.us/img341/3769/entities.gif
As MarketReport.Targets has a join table, map it as many-to-many.
<class name="MarketReport">
<id column="reportid" />
<bag name="ReportTargets" table="reporttargets">
<key column="marketreportid"/>
<many-to-many column="targetid" class="Target"/>
</bag>
</class>
<class name="Target">
<id column="targetid" />
<bag name="DataPoints" inverse="true">
<key column="targetid"/>
<one-to-many class="DataPoint"/>
</bag>
</class>
<class name="DataPoint">
<id column="datapointid" />
</class>
Based on your most recent comment, you want either want a ternary association, or a component collection. I have included both mappings.
<class name="MarketReport">
<id column="reportid" />
<map name="ReportTargets" table="reporttargets">
<key column="marketreportid"/>
<index-many-to-many column="targetid" class="Target"/>
<many-to-many column="datapointid" class="DataPoint"/>
</map>
</class>
<class name="MarketReport">
<id column="reportid" />
<bag name="ReportTargets" table="reporttargets">
<key column="marketreportid"/>
<composite-element class="ReportTarget">
<many-to-one name="Target" column="targetid"/>
<many-to-one name="DataPoint" column="datapointid"/>
</composite-element>
</bag>
</class>
<class name="Target">
<id column="targetid" />
</class>
<class name="DataPoint">
<id column="datapointid" />
</class>

NHibernate not inserting parent into the db

When I save a new Report, NHibernate inserts the Report, ignores the Publication and tries to insert the UserPublication. However SQL then complains about violation of FK constraint.
Its like NHibernate doesn't think the Publication is new even though the row doesn't exist in the db.
Think of the entity relationship as:
A Report can have many Publications (Publications belong to a Report)
A Publication can have many UserPublications (UserPublications belong to a Publication)
Any ideas what I've done wrong?
Thanks in advance.
Here's the mappings:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Model.Report, Model" table="Report" lazy="true">
<id name="Id" access="property" column="ReportID">
<generator class="assigned"></generator>
</id>
<property name="DeleteUnread" access="property" />
<property name="Description" access="property" />
<property name="Name" access="property" />
<bag name="Publications" access="property" lazy="true" cascade="all-delete-orphan">
<key column="ReportID"/>
<one-to-many class="Model.Publication, Model"/>
</bag>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Model.Publication, Model" table="Publication" lazy="true">
<id name="Id" access="property" column="PublicationID">
<generator class="assigned"></generator>
</id>
<property name="CreatedOn" access="property" />
<property name="FileExtension" access="property" />
<property name="IsDownloaded" access="property" />
<property name="ToBeDownloaded" access="property" />
<property name="Name" access="property"/>
<bag name="UserPublications" access="property" lazy="true" cascade="all-delete-orphan">
<key column="PublicationID"></key>
<one-to-many class="Model.UserPublication, Model" />
</bag>
<many-to-one name="Report" class="Model.Report, Model" lazy="false" column="ReportID" not-null="true" cascade="none">
</many-to-one>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Model.UserPublication, Model" table="UserPublication" lazy="true">
<id name="Id" access="property" column="UserPublicationID">
<generator class="native"></generator>
</id>
<property name="IsFlaggedForDeletion" access="property" column="IsFlaggedForDeletion" />
<property name="HasBeenRead" access="property" column="HasBeenRead" />
<property name="DateReceived" access="property" column="DateReceived" />
<property name="MustRead" access="property" column="MustRead" />
<property name="ShowToolbar" access="property" column="ShowToolbar" />
<property name="MaxAge" access="property" column="MaxAge" />
<property name="FeedId" access="property" column="FeedId" />
<property name="CanEdit" access="property" column="CanEdit" />
<many-to-one name="User" access="property" column="ClientUserID" class="Model.ClientUser, Model" not-null="true" cascade="none">
</many-to-one>
<many-to-one name="Publication" access="property" class="Model.Publication, Model" column="PublicationID" not-null="true" cascade="none">
</many-to-one>
</class>
I think the problem is that id of publications is an assigned id therefore NHibernate can't recognize when it should insert a publication.
When you flush a session it first insert all inserted objects , then it updates all updated objects and then deletes all deleted objects.
So I think that's going to happen here:
You save a Report that has publications that have userpublications.Since publication id is assigned NHibernate assumes it has to be updated and ignore it but UserPublication id is native and NHibernates knows when it should be inserted and tries to insert it thus a FK violation happens.
To solve this problem you can add a version property to publication so NHibernate can insert it based on its version value.
The UserPublications bag in the Publication class has a wrong key element. It should be:
<key column="PublicationID"/>
This works. I set the unsaved-value attribute to "any".
I don't think there will be any repurcussions.
<id name="Id" access="property" column="PublicationID" unsaved-value="any">
<generator class="assigned"></generator>
</id>

NHibernate: Mapping multiple classes to the same view

I need to map two different classes to the same view and receive an error that a duplicate mapping exists. Is this possible in NHibernate? If not, can anyone give direction as to how I can solve this mapping problem.
I work with views which are set in stone. One view brings back data needed to split into two classes. The view looks like:
vw_player_points
----------------
Id
GameID
PlayerID
Points
The classes need to be 'player', with a list of games played
select gameid from vw_player_points where playerid = <PlayerID>
And each 'game' needs a list of players and their points:
select playerid, points from vw_player_points where gameid = <GameID>
I've tried table-per-concrete class inheritance aswell as mapping to the same view twice, but have had no joy :(
Here's the 'rough' mappings put into one xml snippet. Notice I also need to map to an interface (which works)
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="Test">
<class name="IPlayer" abstract="true">
<id name="Id" column="id">
<generator class="assigned"/>
</id>
<union-subclass name="Player" table="vw_player">
<bag name="Games">
<key column="player_id"/>
<one-to-many class="Test.IGame" not-found="ignore"/>
</bag>
</union-subclass>
</class>
<class name="IGame" abstract="true">
<id name="Id" column="game_id">
<generator class="assigned"/>
</id>
<union-subclass name="Game" table="vw_player_points">
<bag name="Points">
<key column="game_id"/>
<one-to-many class="Test.IPlayerPoints" not-found="ignore"/>
</bag>
</union-subclass>
</class>
<class name="IPlayerPoints" abstract="true">
<id name="Id" column="id">
<generator class="assigned"/>
</id>
<union-subclass name="PlayerPoints" table="vw_player_points">
<property not-null="false" name="PlayerId" column="player_id"/>
<property not-null="false" name="Points" column="points"/>
</union-subclass>
</class>
</hibernate-mapping>
It seems impossible to map multiple classes to a single view when using abstract/sub-class mapping of the form:
<class name="I[Entity]" abstract="true">
<union-subclass name="[Entity]">
...
</union-subclass>
</class>
I ended up mapping directly to the concrete classes using the proprty-ref attribute which works correctly:
<class name="Game" table="vw_player_points">
<id name="Id" column="id">
<generator class="hilo"/>
</id>
<property not-null="false" name="GameId" column="gameid"/>
<bag name="Points">
<key column="gameid" property-ref="GameId"/>
<one-to-many class="PlayerPoints" not-found="ignore"/>
</bag>
</class>
<class name="PlayerPoints" table="vw_player_points">
<id name="Id" column="id">
<generator class="hilo"/>
</id>
<property not-null="false" name="PlayerId" column="playerid"/>
<property not-null="false" name="Points" column="points"/>
</class>
Perhaps an 'abstract' sub-mapping type would negate the use of the union-subclass hack mapping to interfaces.