I'm trying to map a self-referencing table with NHibernate 3.2.0.4000. However, whenever I get an instance of DomainObject, it eagerly loads the subsequent versions. I'd rather not have to put an extra column my table, though that is an option.
Can I have NHiberante not eagerly load all of the subsequent versions without maintaining the relationship on both sides?
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping assembly="NHibernateHierarchyTest" namespace="NHibernateHierarchyTest" xmlns="urn:nhibernate-mapping-2.2">
<class name="DomainObject" table="DOMAIN_OBJECT" lazy="true" >
<id name="DomainObjectId" column="DOMAIN_OBJECT_ID">
<generator class="identity" />
</id>
<property name="Property">
<column name="PROPERTY" />
</property>
<many-to-one name="PreviousVersion" class="DomainObject" >
<column name="PREVIOUS_VERSION_DOMAIN_OBJECT_ID" />
</many-to-one>
<!--<many-to-one name="SubsequentVersion" class="DomainObject">
<column name="SUBSEQUENT_VERSION_DOMAIN_OBJECT_ID" />
</many-to-one>-->
<one-to-one name="SubsequentVersion" class="DomainObject" property-ref="PreviousVersion" />
</class>
</hibernate-mapping>
The one-to-one mapping will be always loaded eagarly with NHibernate. Not sure if this is a feature or bug, but that is how it works. If you need lazy load, use many-to-one or one-to-many. Not the best answer I know, but if you can add new column...
Related
I'm trying to map the following classes:
PessoaFisica and PessoaJuridica inherits Pessoa.
Cliente has an association with Pessoa, it may be PessoaJuridica or PessoaFisica.
When I save a Cliente object with PessoaFisica, for example, thats ok. But when I try to update and I set the property Pessoa from Cliente to PessoaJuridica and try to update, it updates, but it generates a new row in table TB_PESSOA and the old row, in PessoaFisica is not deleted. It creates a new row to PessoaJuridica, but the old row remains. What's wrong with my mapping XMLs ? Why NHibernate does not delete the old row before insert the new polymorphic object ?
Those are the mapping files I am using
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="SALClassLib.Masterdata.Model" assembly="SALClassLib">
<class name="Pessoa" table="TB_PESSOA">
<id name="Id">
<column name="ID_PESSOA" not-null="true"/>
<generator class="increment" />
</id>
(other properties...)
<joined-subclass name="PessoaFisica" table="TB_PESSOA_FISICA">
<key column="ID_PESSOA" />
(other properties...)
</joined-subclass>
<joined-subclass name="PessoaJuridica" table="TB_PESSOA_JURIDICA">
<key column="ID_PESSOA" />
(other properties...)
</joined-subclass>
</class>
<class name="Cliente" table="TB_CLIENTE">
<id name="Id">
<column name="ID_CLIENTE" not-null="true"/>
<generator class="increment" />
</id>
<many-to-one name="Pessoa" class="Pessoa" cascade="all" column="ID_PESSOA" not-null="true" unique="true" />
Thank you
NHibernate cascading is nicely explained here: NHibernate Cascades: the different between all, all-delete-orphans and save-update
One of the option, is cascade="all-delete-orphan" which could be seen as what you are asking for.
BUT
Cascading deletion of the orphans is correct only in parent-child scenario (no parent ==> no children) or one-to-one mapping. (i.e not vice versa child-parent)
In your case, you do ask for deletion of the referenced object. But NHibernate (well no-one) can know, if it is not referenced by some other "child".
If you need to delete previous Person assigned, you can always do it in code - but explicitly
I am working on an existing data structure that is not perfect and I have an inheritance mapping issue to solve.
I am using a table per hierarchy and have subclasses with discriminators set up. However the subclassed properties are foreign keys back to other tables. How do I set up my subclass mapping so that when I query the fk property I get an object rather than null? Is this even possible?
My current Mapping
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MVC3" namespace="MVC3.Models">
<class name="Image" table="Images">
<id name="Id" column="ImageId">
<generator class="identity" />
</id>
<discriminator column="ImageType" />
<property name="Url" column="Url" not-null="true" />
<property name="Caption" column="Caption" />
<subclass name="AupairImage" discriminator-value="AupairImage">
<join table="Aupairs" inverse="true">
<key column="AupairId" />
<many-to-one name="Aupair" column="AupairId" class="Aupair" />
</join>
</subclass>
<subclass name="FamilyImage" discriminator-value="FamilyImage">
<join table="Families" inverse="true">
<key column="FamilyId" />
<many-to-one name="Family" column="FamilyId" class="Family" />
</join>
</subclass>
I would have like to add an entity diagram but I cannot post images yet :0(
But the foreign keys AupairId and FamilyId link off back to two other tables and are of the type int 32
I know it would be better to restructure the Aupair And Family entities to have a hierarchy to get rid of the one in images but this would be a last resort due to existing code.
Thanks in advance any help appreciated from you mapping experts....
Realised what I was doing wrong after taking a second look, should have just used a Many-To-One under the Subclass with a defined column
<subclass name="MVC3.Models.FamilyImage, MVC3" discriminator-value="FamilyImage">
<many-to-one cascade="all" class="MVC3.Models.Family, MVC3" name="Family">
<column name="FamilyId" />
</many-to-one>
</subclass>
we use an external Database where we cant edit table designs only add own tables to extend the core tables.
So I need map two tables on one class, i try this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DaVinci"
namespace="DaVinci.Domain">
<class name="Vorgang" table="VORGANGSKOPF">
<id name="Id" column="ID">
<generator class="native" />
</id>
<property name="Vorgangsnummer" column="VORGANG" />
...
<join table="OWN_VORGANG_WAEHRUNG" optional="true">
<key column="VOR_ID" property-ref="Vorgangsnummer" />
<property name="WaehrungVK_Internet" column="WAEHRUNG" />
<property name="WaehrungsKursVK_Internet" column="KURS" />
<property name="Preis_Internet" column="BETRAG_EURO" />
<property name="PreisFremdWaehrung_Internet" column="BETRAG_FREMD" />
</join>
...
After testing i know now that "property-ref" for joins dosn't work.
Bugreport here
Does anyone know an other way to map two tables on one class?
(I'm struggling a little with the table and column names here.)
Could you use a joined subclass for this? Even if the tables don't follow the logical relationship, if there's a 1-to-1 database relationship between the two tables, then you'd get what you want by ignoring the parent, and doing all your operations on the subclass.
I have a Member Table with fields
MemID - Primary Key
Business_Name
Business_Address
Business_Phone
I need to make an Employer Class which has properties that come from the same Members Table.
EmployerName
EmployerAddress
EmployerPhone
Here is my Employer Mapping
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Employer, Entities" lazy="true" table="Members" dynamic-update="true">
<id name="MemberID" column="MemID" type="Int64">
<generator class="native" />
</id>
<many-to-one name="EmployerAddress" column="Business_Address" class="Address, Entities" lazy="proxy" />
<many-to-one name="EmployerPhone" column="Business_Phone" class="Phone, Entities" lazy="proxy"/>
<property name="EmployerName" column="Business_Name" not-null="false" />
</class>
</hibernate-mapping>
I thought that I could map the Members class like this but I get a "System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary."
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="Member, Entities" lazy="true" table="Members" dynamic-update="true">
<id name="MemberID" column="MemID" type="Int64">
<generator class="native" />
</id>
<one-to-one name="EmployerInformation" class="Employer, Entities" lazy="false"/>
</class>
</hibernate-mapping>
Also please note. I can't move the Business Information to another table due to constraints on the current system. Business_Address and Business_Phone are FK to another table that is why they are many-to-one mappings.
I'm not sure if this is what you're looking for, but you could try the "component" mapping. This allows you to have a nested class within the same table.
Search google for "nhibernate component" - it appears that the hibernate.org site is still down (!), but you might be able to get the component info from the google cache for the page "Chapter 7 - Component Mapping."
We have a legacy database schema which I've tried (unsuccessfully) to map with NHibernate. To give a simplified example, say I want a Person class whose first name comes from the "Person" table, but their last name comes from the "Person2" table. The "Person" table also has the Id of the person's Car and I want my Person class to have a Car property. I can map all that using the following;
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="NHibernateMappingTest.Person, NHibernateMappingTest" lazy="false">
<id name="Id" >
<generator class="native" />
</id>
<property name="FirstName" />
<many-to-one name="Car" access="property" class="NHibernateMappingTest.Car, NHibernateMappingTest" column="CarId" cascade="save-update"/>
<join table="Person2">
<key column="PersonId" />
<property name="LastName" />
</join>
</class>
</hibernate-mapping>
The lets me combine the Person and Person2 tables, and the lets me find their Car - everything works fine.
But... if the Person2 table happens to have the person's HouseId, I'd like to be able to add a second element to my mapping...
<many-to-one name="House" access="property" class="NHibernateMappingTest.House, NHibernateMappingTest" column="HouseId" cascade="save-update"/>
...so that my Person class can have a House property.
However this is where it all goes wrong, because the SQL which NHibernate generates assumes that the HouseId column is in the Person table (but it's not, it's in Person2), so I get the following error;
MySql.Data.MySqlClient.MySqlException: #42S22Unknown column 'HouseId' in 'field list'
Is NHibernate able to do what I'm attempting, is there a different way to achieve this (without changing the database schema), or have I just made a beginner's error in my map file?
Vincent - thanks for your response. No I wasn't nesting the tag element inside the element. But following your suggestion, I tried and it works perfectly! Thanks very much for responding.
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="NHibernateMappingTest.Person, NHibernateMappingTest" lazy="false">
<id name="Id" >
<generator class="native" />
</id>
<property name="FirstName" />
<many-to-one name="Car" access="property" class="NHibernateMappingTest.Car, NHibernateMappingTest" column="CarId" cascade="save-update"/>
<join table="Person2">
<key column="PersonId" />
<property name="LastName" />
<many-to-one name="House" access="property" class="NHibernateMappingTest.House, NHibernateMappingTest" column="HouseId" cascade="save-update"/>
</join>
</class>
</hibernate-mapping>