"many-to-one" within component problem NHibernate - 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.

Related

NHibernate AssertException: Interceptor.OnPrepareStatement(SqlString) returned null or empty SqlString

I am trying to switch a table from being a many-to-one mapping to being many-to-many with an intermediate mapping table. However, when I switched it over and tried to do a query on it with NHibernate, it's giving me this error: "Interceptor.OnPrepareStatement(SqlString) returned null or empty SqlString."
My query was originally something more complex, but I switched it to a basic fetch all and I'm still having the problem:
Session.QueryOver<T>().Future();
It would seem to either be a problem in my model mapping files or something in my database.
Here are my model mappings:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="GBI.Core" namespace="GBI.Core.Models">
<class name="Market" table="gbi_Market">
<id name="Id" column="MarketId">
<generator class="identity" />
</id>
<property name="Name" />
<property name="Url" />
<property name="Description" type="StringClob" />
<property name="Rating" />
<property name="RatingComment" />
<property name="RatingCommentedOn" />
<many-to-one name="RatingCommentedBy" column="RatingCommentedBy" lazy="proxy"></many-to-one>
<property name="ImageFilename" />
<property name="CreatedOn" />
<property name="ModifiedOn" />
<property name="IsDeleted" />
<many-to-one name="CreatedBy" column="CreatedBy" lazy="proxy"></many-to-one>
<many-to-one name="ModifiedBy" column="ModifiedBy" lazy="proxy"></many-to-one>
<set name="Content" where="IsDeleted=0 and ParentContentId is NULL" order-by="Ordering asc, CreatedOn asc, Name asc" lazy="extra">
<key column="MarketId" />
<one-to-many class="MarketContent" />
</set>
<set name="FastFacts" where="IsDeleted=0" order-by="Ordering asc, CreatedOn asc, Name asc" lazy="extra">
<key column="MarketId" />
<one-to-many class="MarketFastFact" />
</set>
<set name="NewsItems" table="gbi_NewsItem_Market_Map" lazy="true">
<key column="MarketId" />
<many-to-many class="NewsItem" fetch="join" column="NewsItemId" where="IsDeleted=0"/>
</set>
<!--<set name="MarketUpdates" table="gbi_Market_MarketUpdate_Map" lazy="extra">
<key column="MarketId" />
<many-to-many class="MarketUpdate" fetch="join" column="MarketUpdateId" where="IsDeleted=0" order-by="CreatedOn desc" />
</set>-->
<set name="Documents" table="gbi_Market_Document_Map" lazy="true">
<key column="MarketId" />
<many-to-many class="Document" fetch="join" column="DocumentId" where="IsDeleted=0"/>
</set>
</class>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="GBI.Core" namespace="GBI.Core.Models">
<class name="MarketUpdate" table="gbi_MarketUpdate">
<id name="Id" column="MarketUpdateId">
<generator class="identity" />
</id>
<property name="Description" />
<property name="CreatedOn" />
<property name="ModifiedOn" />
<property name="IsDeleted" />
<!--<many-to-one name="Market" column="MarketId" lazy="proxy"></many-to-one>-->
<set name="Comments" where="IsDeleted=0" order-by="CreatedOn desc" lazy="extra">
<key column="MarketUpdateId" />
<one-to-many class="MarketUpdateComment" />
</set>
<many-to-one name="CreatedBy" column="CreatedBy" lazy="proxy"></many-to-one>
<many-to-one name="ModifiedBy" column="ModifiedBy" lazy="proxy"></many-to-one>
</class>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="GBI.Core" namespace="GBI.Core.Models">
<class name="MarketUpdateMarketMap" table="gbi_Market_MarketUpdate_Map">
<id name="Id" column="MarketUpdateMarketMapId">
<generator class="identity" />
</id>
<property name="CreatedOn" />
<property name="ModifiedOn" />
<property name="IsDeleted" />
<many-to-one name="CreatedBy" column="CreatedBy" lazy="proxy"></many-to-one>
<many-to-one name="ModifiedBy" column="ModifiedBy" lazy="proxy"></many-to-one>
<many-to-one name="MarketUpdate" column="MarketUpdateId" lazy="proxy"></many-to-one>
<many-to-one name="Market" column="MarketId" lazy="proxy"></many-to-one>
</class>
As I mentioned, MarketUpdate was originally a many-to-one with Market (MarketId column is still in there, but I'm ignoring it. Could this be a problem?). But I've added in the Market_MarketUpdate_Map table to make it a many-to-many.
I'm running in circles trying to figure out what this could be. I couldn't find any reference to this error when searching. And it doesn't provide much detail.
Using:
NHibernate 2.2
.NET 4.0
SQL Server 2005
Turns out the problem was just that the xml mapping file was set as content instead of embedded resource in visual studio. Changing that fixed all my problems.
If you're using Fluent rather than xml for mappings and encounter this issue, try deleting the generated xml files in %root%\LocalCache\NHibernate.

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();
?

NHibernate Mapping + Iset

I have a mapping file
<set name="Friends" table="Friends">
<key column="UserId"/>
<many-to-many class="User" column="FriendId"/>
</set>
I would like to specify extra columns for the friend table this creates.
For example Approve (the user must approve the friend request)
Is there a easy way?
And update
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="MyVerse.Domain" assembly="MyVerse.Domain" xmlns="urn:nhibernate-mapping-2.2">
<class name="User" table="[User]" lazy="true">
<id name="Id" type="Guid">
<generator class="guid" />
</id>
<property name="DateCreated" type="DateTime" not-null="true" />
<property name="Deleted" type="Boolean" not-null="true" />
<property name="Firstname" type="String" length="100" not-null="true" />
<property name="Lastname" type="String" length="100" not-null="true" />
<bag name="Friends" table="[Friend]">
<key column="UserId"/>
<many-to-many class="Friend" column="FriendId"/>
</bag>
</class>
<class name="Friend" table="[Friend]" lazy="true">
<id name="Id" type="Guid">
<generator class="guid" />
</id>
<property name="DateCreated" type="DateTime" not-null="true" />
<property name="Approved" type="Boolean" not-null="true" />
</class>
</hibernate-mapping>
Will cause a link to the friend table from the friend table
If a set has "extra properties", you must convert it into a proper entity.
So, a User doesn't have an ISet<User>; it has an ISet<Friend>.

Many to one mapping problem with 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.

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