nhibernate cant not save or SaveOrUpdate - nhibernate

It took me so much time . Im lost in it .
I make the program read from a XML and deserialize it to Object with the primary key 'id' .But using both 'SaveOrUpdate' and 'Save' method cant not make the data insert into database .
and Log4Net not error. no insert log. no exception happened.
Somebody helps me.
Today I tried to add a primary key 'HotelId' in the table and it's identity ,and works .
How to make it work without an extra primary key.
because the id in XML is unique. so I do not wanna add extra primary key.
fllowing is part of *.hbm.xml
<id name="id" column="id" type="string" >
<generator class="assigned"/>
</id>
<property name="dateUpdated" column="dateUpdated" type="DateTime" />
<property name="name" column="name" type="string" />
<property name="address" column="address" type="string" />
<property name="zip" column="zip" type="string" />
while I add a extra primary not in XML ,it works like following :
<id name="Id" column="HotelId" type="int" unsaved-value="0" >
<generator class="native"/>
</id>
<property name="id" column="id" type="string" />
<property name="dateUpdated" column="dateUpdated" type="DateTime" />
<property name="name" column="name" type="string" />
<property name="address" column="address" type="string" />
<property name="zip" column="zip" type="string" />

my crystal ball tells me you do not use transactions.Commit(); nor session.Flush(); to tell the session you have done your work and want the changes persisted. I Hope it's not broken

Related

NHibernate 2nd level cache does not invalidate entities map on the same table

I'm using NHibernate 3.2 with appfabric 1.1 for the 2nd level cache.
I’ve 2 classes mapped on the same table. The first class AFullEntity (MonitorLayoutData in the sample), inherit a second class which is lightweight class (MonitorLayout). MonitorLayoutData contains a heavy property that is not present in the base class. For example :
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Entities.MonitorLayout,Entities" table="MonitorLayouts2" lazy="false" schema="dbo" polymorphism="explicit">
<cache usage="nonstrict-read-write"/>
<id name="Id" column="MonitorLayout_ID" type="int">
<generator class="native" />
</id>
<property name="Name" column="MonitorLayout" type="string" />
<property name="UserId" column="User_ID" type="int" />
<property name="IsPublic" column="IsPublic" type="Boolean" not-null="true" />
<property name="ViewGuid" column="ViewGuid" type="string" not-null="true" />
<property name="TreeNode" column="TreeNode" type="string" />
<property name="IncludeNodeChildren" column="IncludeNodeChildren" type="Boolean" />
</class>
<class name="Entities.MonitorLayoutData,Entities" table="MonitorLayouts2" lazy="false" schema="dbo" polymorphism="explicit">
<cache usage="nonstrict-read-write"/>
<id name="Id" column="MonitorLayout_ID" type="int">
<generator class="native" />
</id>
<property name="Name" column="MonitorLayout" type="string" />
<property name="UserId" column="User_ID" type="int" />
<property name="IsPublic" column="IsPublic" type="Boolean" not-null="true" />
<property name="ViewGuid" column="ViewGuid" type="string" not-null="true" />
<property name="TreeNode" column="TreeNode" type="string" />
<property name="IncludeNodeChildren" column="IncludeNodeChildren" type="Boolean" />
<property name="LayoutData" column="LayoutData" type="BinaryBlob" not-null="false"/>
</class>
</hibernate-mapping>
Those classes use an explicit polymorphism to retrieve only entities for the selected type like note in the documentation : “Explicit polymorphism is useful when two different classes are mapped to the same table (this allows a "lightweight" class that contains a subset of the table columns)”.
However I got a problem when entities are cached. When I update a AFullEntity changes are not report in the lightweight class and this is a big problem for us.
I try other mechanism like subclass or extends but NHibernate force me to declare a discriminator element, which is not required for me.
Is there a way to do this ?
No, they are two separate objects, each with their own identity in the cache. Possible workaround would be to disable caching for lightweight objects or evict the lightweight object from the cache when the heavy object is loaded. Loading the heavy and light objects in the same session seems to me to defeat the purpose.

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.

NHibernate create IMAGE instead VarBinary(max)

I use the fallowing NHibernate Mapping (NH 3.2) with MS SQL Server 2008 (set MsSql2008Dialect):
<class name="Layout" table="Layout" lazy="false" >
<cache usage="read-write"/>
<id name="Id" column="Id" type="Guid">
<generator class="assigned"/>
</id>
<version name="ObjectVersion" column="ObjectVersion"/>
<property name="Key" column="Key" type="String" length="255" not-null="true" />
<property name="Value" column="Value" type="BinaryBlob" length="2147483647" />
<property name="Created" column="Created" type="Timestamp" not-null="true" optimistic-lock="false" />
<property name="CreatedBy" column="CreatedBy" type="String" length="255" not-null="true" optimistic-lock="false" />
<property name="Changed" column="Changed" type="Timestamp" optimistic-lock="false" />
<property name="ChangedBy" column="ChangedBy" type="String" length="255" optimistic-lock="false" />
<many-to-one name="User" class="User" foreign-key="FK_User_Layout" lazy="proxy" fetch="select">
<column name="UserId"/>
</many-to-one>
</class>
The Problem is here, that for the Column Value, NHibernate will create a Field of IMAGE. But I need VarBinary(max). What is wrong with the mapping?
I have the same problem after migration from version 3.1 to 3.2.
I think this is a bug.
I have explored source code version 3.1 and 3.2 and have found some difference which changed initialization sequence for MsSqlDialect* classes.
I fixed it by creating descendant of dialect class and overriding method "RegisterLargeObjectTypeMappings"
public class MyMsSql2008Dialect : MsSql2008Dialect
{
protected override void RegisterLargeObjectTypeMappings()
{
base.RegisterLargeObjectTypeMappings();
base.RegisterColumnType(DbType.Binary, 2147483647, "VARBINARY(MAX)");
}
}
Try this
<property name="Value">
<column name="Value" sql-type="varbinary(max)" />
</property>

HQL: query only base table from <join> entity

I have this mapping
<class name="Person" table="person">
<id name="Id" column="id" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="Code" column="code" type="String" not-null="true" />
<property name="FirstName" column="firstName" type="String" not-null="true" />
<property name="MiddleName" column="middleName" type="String" not-null="false" />
<property name="LastName" column="lastName" type="String" not-null="false" />
<join table="personPhoto" optional="true">
<key column="personId" />
<property name="Photo" column="pictureContent" not-null="false" />
</join>
and the generated SQL always use left outer join, which is correct.
However, is it possible to tell HQL to query only from person table, since I'm not always need 'Photo' property? And how?
Is there a one-to-one relationship between person and personPhoto columns?
If you want to load the person's photo lazily, I believe you have to change join mapping to one-to-one mapping and create a new class for personPhoto. This way Hibernate would be able to insert a proxy object.

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.