Many to one mapping problem with NHibernate - nhibernate

Firstly I am relatively new to NHibernate. Got two tables on TaxMapping and Address. A single TaxMapping must have one address and one address can belong to more than one Tax Mapping. They are linked through foreign key
TaxMapping hbm
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="ITAPDTO" assembly="ITAPDTO">
<class name="TaxMapping" table="tblTaxMapping">
<id name="Tax_Mapping_ID">
<column name="Tax_Mapping_ID" sql-type="bigint" not-null="true"/>
<generator class="identity" />
</id>
<property name="Tax_ID" />
<property name="Client_Code" />
<property name="NRA_Sub_Account" />
<property column="Domicile" type="String" name="Domicile" length="5" />
<many-to-one name="Address" column="AddressID" cascade="none" not-found="exception" not-null="true" fetch="join" class="ITAPDTO.Address,ITAPDTO" />
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="ITAPDTO" assembly="ITAPDTO">
<class name="Address" table="Address">
<id name="AddressID" column="AddressID" type="Int32" unsaved-value="0">
<generator class="identity"/>
</id>
<property column="Client" type="String" name="Client" not-null="true" length="100" />
<property column="Contact" type="String" name="Contact" not-null="true" length="50" />
<property column="Address1" type="String" name="Address1" not-null="true" length="100" />
<property column="Address2" type="String" name="Address2" not-null="true" length="100" />
<property column="Address3" type="String" name="Address3" not-null="true" length="100" />
<property column="City" type="String" name="City" not-null="true" length="50" />
<property column="State" type="String" name="State" not-null="true" length="50" />
<property column="PoBox" type="String" name="PoBox" not-null="true" length="50" />
<property column="PostCode" type="String" name="PostCode" not-null="true" length="20" />
<property column="Country" type="String" name="Country" not-null="true" length="50" />
<property column="InsertedBy" type="String" name="Modified_By" length="20" />
<property column="InsertedOn" type="DateTime" name="Modified_Date" />
<property column="ConfirmedBy" type="String" name="Approved_By" length="20" />
<property column="ConfirmedOn" type="DateTime" name="Approved_Date" />
<property column="Status" type="String" name="Status" />
<property column="IUD" type="String" name="IUD" />
</class>
</hibernate-mapping>
I can pull in the data and bind to grid view with no issue. However when I update the Taxmapping the AddressID for the Address oject is always null event thoughh the other address fields are correctly populated and I dont know why. I currently have a hack in place the pulls the id from the db before I call update but I really shouldn't have to do this. Any thoughts would be welcome
regards

Is this due to cascade being set to "none" on the Taxmapping object's Address property? Try changing it to "save-update". You may also want to read the nhibernate documentation to figure out which cascade setting would be best for your situation, though it sounds like "save-update" would be most appropriate.

In addition to Krazzy's point, you should also check that your sessions are closed and / or flushed appropriately. A long-running session which is never flushed can exhibit similar problems.

Related

Session.Get and Session.Load commands ignore filters

I'm using a mapping with a filter.
But when I try to persist my object, it first wants to get a snapshot (because my Id is a string).
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DomainLayer.General" assembly="DomainLayer">
<class name="Fund" table="OPENA_BriefW" lazy="false">
<id name="Id" column="`BRWNUMMER`" type="string" >
</id>
<property name="Name" column="`BRWNAAM`" type="string" />
<property name="Contact" column="`BRWNAAM2`" type="string" />
<property name="Address" column="`BRWADRES`" type="string" />
<property name="City" column="`BRWSTAD`" type="string" />
<property name="Zip" column="`BRWPOST`" type="string" />
<property name="Phone" column="`BRWTELEFOON`" type="string" />
<property name="Fax" column="`BRWTELEFAX`" type="string" />
<property name="Iban" column="`brw_iban`" type="string" />
<property name="BankAccount" column="`BRWBANKNU`" type="string" />
<property name="Swift" column="`brw_swift`" type="string" />
<property name="ReceiveOffice" column="`BRWONTVKANT`" type="int" />
<property name="RegionDirection" column="`BRWGEWESTDIR`" type="int" />
<many-to-one name="Country" class="DomainLayer.General.CodeDescription" fetch="join" not-found="ignore">
<formula>'ALG'</formula>
<formula>'0'</formula>
<formula>'WG030'</formula>
<column name="`BRWLAND`" />
<formula>:LanguageFilter.Id</formula>
</many-to-one>
</class>
</hibernate-mapping>
As you can see the filter :LanguageFilter.Id is the one causing the troubles. When I do a normal .List() it doesn't cause problems.
But when I persist, it first wants to check if the Fund already exists yes/no. By doing a .Get (with the Id).
Then I get the error can't retrieve snapshot because in my query he doesn't replace :LangaugeFilter.Id with the effective value i set on my session.
I enable the filter on my session like so:
session.EnableFilter("LanguageFilter").SetParameter("Id", 1);
Here's the filter-def mapping:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<filter-def name='LanguageFilter' >
<filter-param name='Id' type='System.Int32' />
</filter-def>
</hibernate-mapping>
This post (comment 4) http://ayende.com/blog/3993/nhibernate-filters says that session.Get and Load ignores filters.
Are there any alternatives, because I need that language to be variable.
Ok, what I did was the following: I didn't use SaveOrPersist, but Save when new and Persist when I had an old one. This didn't execute the extra get.

Could you help me to configure the store procedure in the NHibernate config file?

In my program, i need get a exec a store procedure to decide to get a object from which table, so i need config a stored procedure in my entity nhibernate config file, the config file like below:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Entity.ACC.User, Entity" table="ACC_User" lazy="false">
<id name="Id" column="Id" type="Int32" unsaved-value="0" >
<generator class="increment" />
</id>
<property name="Code" column="Code" type="String" length="50" />
<property name="Password" column="Password" type="String" length="50" />
<property name="FirstName" column="FirstName" type="String" length="50" />
<property name="LastName" column="LastName" type="String" length="50" />
<property name="Type" column="Type" type="Int16" />
<property name="Email" column="Email" type="String" length="50" />
<property name="TelPhone" column="TelPhone" type="String" length="50" />
<property name="MobilePhone" column="MobilePhone" type="String" length="50" />
<property name="Language" column="Language" type="String" length="50" />
<property name="IsActive" column="IsActive" type="Boolean" />
<property name="AccountExpired" column="AccountExpired" type="Boolean" />
<property name="AccountLocked" column="AccountLocked" type="Boolean" />
<property name="PasswordExpired" column="PasswordExpired" type="Boolean" />
<property name="CreateUserId" column="CreateUser" type="Int32" update="false" />
<property name="CreateUserName" column="CreateUserNm" type="String" length="100" update="false" />
<property name="CreateDate" column="CreateDate" type="DateTime" update="false" />
<property name="LastModifyUserId" column="LastModifyUser" type="Int32" />
<property name="LastModifyUserName" column="LastModifyUserNm" type="String" length="100" />
<property name="LastModifyDate" column="LastModifyDate" type="DateTime" />
<sql-insert>
exec USP_User_Insert ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
</sql-insert>
<sql-update>
exec USP_User_Update ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
</sql-update>
<sql-delete>
exec USP_User_Delete ?
</sql-delete>
</class>
<sql-query name="User_Select">
<return class="Entity.ACC,Entity.ACC.User"/>
exec USP_User_Select ?
</sql-query>
</hibernate-mapping>
after i added this query SP in the config file
exec USP_User_Select ?
the program can't run and will throw exception as:
unknown class Entity.ACC, Entity.ACC.User
what should i do let the SP work.
many thanks.
Try changing
return class="Entity.ACC,Entity.ACC.User"
line into
return class="Entity.ACC.User, Entity"

Saving manually created objects using NHibernate

I am trying to use NHibernate to save an object that was completely manually created. My mappings are in place and I currently have no data in the database. Everytime I call Save() or SaveOrUpdate(), NHibernate does a select statement for what I am trying to save. Then it gives me the exception: "a different object with the same identifier value was already associated with the session". Does anyone know how I can tell NHibernate to save my manually instantiated object without thinking that a different object has already been loaded?
Additional Information:
I have a primary mapping with a one-to-many collection. The exception is telling me that "a different object with the same identifier has been loaded", on the collection, not the parent object. I don't know if this provides any useful information. The mappings are as follows:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Program.Application.Models" assembly="Company.Application.Models">
<class name="ProductVersion" table="ClientVersion" lazy="false">
<composite-id>
<key-property name="PracticeName">
<column name="practiceName" not-null="true" />
</key-property>
<key-property name="Address">
<column name="address" not-null="true" />
</key-property>
<key-property name="City">
<column name="city" not-null="true" />
</key-property>
<key-property name="State">
<column name="state" not-null="true" />
</key-property>
<key-property name="Zip">
<column name="zip" not-null="true" />
</key-property>
</composite-id>
<property name="LegalName" column="legalName" />
<property name="Version" column="version" />
<bag name="ProductsLicensesDetail" inverse="true" lazy="false" >
<key>
<column name="practiceName" />
<column name="address" />
<column name="city" />
<column name="state" />
<column name="zip" />
</key>
<one-to-many class="ProductLicenseDetail" />
</bag>
</class>
</hibernate-mapping>
and
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Program.Application.Models" assembly="Program.Application.Models">
<class name="ProductLicenseDetail" table="ClientProductLicense">
<id name="ProductCode" column="productCode">
<generator class="assigned" />
</id>
<property name="TotalEnterpriseLicenses" column="totalEnterpriseLicenses" />
<property name="EnterpriseLicensesUsed" column="enterpriseLicensesUsed" />
<property name="TotalPracticeLicenses" column="totalPracticeLicenses" />
<property name="PracticeLicensesUsed" column="practiceLicensesUsed" />
<property name="TotalProviderLicenses" column="totalProviderLicenses" />
<property name="ProviderLicensesUsed" column="providerLicensesUsed" />
<property name="TotalUserLicenses" column="totalUserLicenses" />
<property name="UserLicensesUsed" column="userLicensesUsed" />
<property name="LicenseKey" column="licenseKey" />
<property name="LicenseActivationDate" column="licenseActivationDate" />
<property name="LicenseExpirationDate" column="licenseExpirationDate" />
<many-to-one name="ProductVersion" class="ProductVersion" cascade="none">
<column name="practiceName" />
<column name="address" />
<column name="city" />
<column name="state" />
<column name="zip" />
</many-to-one>
</class>
</hibernate-mapping>
NHibernate is telling me that "a different object with the same identifier value was already associated with the session" for the ProductCode key of the second mapping. Any insight would greatly be appreciated. Thank you.
I believe you will need to add a version field to your composite key class and mapping; see this article for further details.
Have you tried
session.SaveOrUpdateCopy(entity);
session.Flush();
?

"many-to-one" within component problem NHibernate

With the following mapping, BillingAddress.Country is mapped correctly but ShippingAddress.Country is always null. Maybe it's because of equal properties name? but they are different objects... Any idea how to fix it?
Thanks ahead.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="KapsNet.QuickOffice.Models" namespace="KapsNet.QuickOffice.Dto">
<class name="Order" table="`Order`" >
<id name="ID" type="System.Int32" column="ID">
<generator class="identity"/>
</id>
<property name="CreateDate" column="CreateDate" type="System.DateTime" not-null="true" />
<property name="ClientContactID" column="ClientContactID" type="System.Int32" not-null="true" />
<component name="BillingAddress" class="AddressInfo">
<property name="Address" column="BillingAddress" type="System.String" not-null="false" length="255"/>
<property name="ZipCode" column="BillingZipCode" type="System.String" not-null="false" length="50"/>
<property name="City" column="BillingCity" type="System.String" not-null="false" length="50"/>
<property name="CountryID" column="BillingCountryID" type="System.Int32" not-null="true" />
<property name="Phone" column="BillingPhone" type="System.String" not-null="false" length="50"/>
<many-to-one name="Country" column="BillingCountryID" class="Country" update="0" insert="0" />
</component>
<component name="ShippingAddress" class="AddressInfo">
<property name="Address" column="ShippingAddress" type="System.String" not-null="false" length="255"/>
<property name="ZipCode" column="ShippingZipCode" type="System.String" not-null="false" length="50"/>
<property name="City" column="ShippingCity" type="System.String" not-null="false" length="50"/>
<property name="CountryID" column="ShippingCountryID" type="System.Int32" not-null="true" />
<property name="Phone" column="ShippingPhone" type="System.String" not-null="false" length="50"/>
<many-to-one name="Country" column="ShippingCountryID" class="Country" update="0" insert="0" />
</component>
<many-to-one name="ClientContact" column="ClientContactID" class="ClientContact" update="0" insert="0" />
<bag name="OrderItemList" table="OrderItem" inverse="true" lazy="true" cascade="delete">
<key column="OrderID" />
<one-to-many class="OrderItem"/>
</bag>
</class>
</hibernate-mapping>
You should remove CountryID from the mappings for billing and shipping address because it is already defined in the many-to-one relationship to Country. Other than that the mappings look okay. Components will be null if all of the values in the component are null. So, if all of the shipping address fields are null then the ShippingAddress component will be null.

nhibernate many-to-many bag not inserting in the association table

I know this has been asked and answered a number of times, but I have two classes that are many-to-many. I've reciprocal mapped them using bags. Here is the NHibernate Mapping:
Calendar:
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by NHibernate.Mapping.Attributes on 2009-10-09 18:09:29Z.-->
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Calendar.Calendar, Calendar" table="Calendars">
<id name="CalendarId" column="CalendarId" type="Int32">
<generator class="native" />
</id>
<property name="Name" length="100" />
<property name="CalendarStatus" />
<property name="CalendarType" type="Calendar.GenericEnumMapper`1[[Calendar.CalendarType, Calendar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Calendar" length="50" />
<property name="RecordCreatedBy" column="CreatedBy" length="50" />
<property name="RecordModifiedBy" column="ModifiedBy" length="50" />
<property name="CreateDate" />
<property name="ModifiedDate" />
<bag name="Events" table="CalendarEventsInCalendar" cascade="all">
<key column="CalendarId" />
<many-to-many class="Calendar.CalendarEvent, Calendar" column="CalendarEventId" />
</bag>
</class>
</hibernate-mapping>
CalendarEvent:
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by NHibernate.Mapping.Attributes on 2009-10-09 18:27:46Z.-->
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Calendar.CalendarEvent, Calendar" table="CalendarEvents">
<id name="CalendarEventId" column="CalendarEventId" type="Int32">
<generator class="native" />
</id>
<property name="EventStatus" />
<property name="StartTime" />
<property name="EndTime" />
<property name="ImageUrl" length="255" />
<property name="Description" length="2000" />
<property name="LocationName" length="255" />
<property name="Address1" length="255" />
<property name="Address2" length="255" />
<property name="City" length="255" />
<property name="State" length="255" />
<property name="Zip" length="10" />
<property name="Title" length="255" />
<property name="Url" length="255" />
<property name="ExternalSystemId" />
<property name="ExternalSystem" type="Calendar.GenericEnumMapper`1[[Calendar.ExternalSystemType, Calendar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Calendar" length="50" />
<property name="RecordCreatedBy" column="CreatedBy" length="50" />
<property name="RecordModifiedBy" column="ModifiedBy" length="50" />
<property name="CreateDate" />
<property name="ModifiedDate" />
<many-to-one name="ParentEvent" column="ParentEventId" />
<bag name="ChildEvents" lazy="true" fetch="subselect" cascade="all" inverse="true">
<key column="ParentEventId" />
<one-to-many class="Calendar.CalendarEvent, Calendar" />
</bag>
<bag name="Calendars" table="CalendarEventsInCalendar" lazy="false" inverse="true">
<key column="CalendarEventId" />
<many-to-many class="Calendar.Calendar, Calendar" column="CalendarId" />
</bag>
</class>
</hibernate-mapping>
And here's how I add an Event to a Calendar:
public virtual void AddEvent(CalendarEvent calEvent)
{
if(!calEvent.Calendars.Contains(this))
calEvent.Calendars.Add(this);
Events.Add(calEvent);
}
Then I do a SaveOrUpdate(calendar)
Any ideas?
You have to wrap the SaveOrUpdate in a transaction and then do Transaction.Commit(). Otherwise, the Mapping doesn't save, only the entities.
Thanks,
Jason
I think the problem is in inverse=true for CalendarEvent. You should remove it