Hi
I have parent and child table like below
<?xml version="1.0" encoding="utf-8"?>
------- parent --------------
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="HibernateSample.StudMarks,HibernateSample" table="StudMarks" lazy="false">
<id name="Sno" column="SNO" type="int">
<generator class="assigned"/>
</id>
<many-to-one name="Student" column="ID" not-null="true"/>
<property name="Marks" column="Marks" type="int" not-null="true" />
<property name="Rank" column="Rank" type="int" not-null="true" />
</class>
</hibernate-mapping>
------- child --------------
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="HibernateSample.Student,HibernateSample" table="Student" lazy="false">
<id name="Id" column="ID" type="int">
<generator class="native" />
</id>
<property name="Name" column="Name" type="string" not-null="true" />
<property name="Standard" column="Standard" type="string" not-null="true" />
<bag name="StudMarks" cascade="all" lazy="false">
<key column="ID" not-null="true"/>
<one-to-many class="HibernateSample.StudMarks,HibernateSample" />
</bag>
</class>
</hibernate-mapping>
and in .cs file i have like written code like below to insert into parent and child.
StudMarks sm = new StudMarks();
Student st = new Student();
List<StudMarks> sms = new List<StudMarks>();
st.Id = 9;
st.Name = "stud 999";
st.Standard = "99";
sm.Sno = 9;
sm.Marks = 99;
sm.Rank = 9;
sm.Student = st; ------ **Line 1**
st.StudMarks = sms; ------ **Line 2**
session.Save(sm);
session.Flush();
If i commENT "Line 1" in above code only child is inserting. If i comment "Line 2" foreign key constraint error is throwing.
Tables:
CREATE TABLE [dbo].[Student](
[ID] [int] IDENTITY(1,1) NOT NULL, -- PRIMARY KEY
[Name] [varchar](50) NOT NULL,
[Standard] [varchar](50) NOT NULL,
CREATE TABLE [dbo].[StudMarks](
[SNO] [int] NOT NULL, -- PRIMARY KEY
[ID] [int] NOT NULL, -- FOREIGN KEY
[Marks] [int] NOT NULL,
[Rank] [int] NOT NULL,)
Please let me know how to insert in parent and child at a time in single save operation.
You have a cascade relation from Student->StudentMarks. So you should be saving st...
session.Save(st);
You should also specify inverse="true" on the bag so you don't get double updates of the foreign key and a cascade="all-delete-orphan" is probably appropriate here as you want all StudentMarks to be deleted when the Student is deleted.
I believe you need to specify inverse="true" on the Student mapping of the StudMarks collection property, indicating that the StudMark mapping is the owner of the relationship.
Related
i want to do a left outer join from 2 table, but with 2 key that are not primary key.
This is the native sql query used:
Maybe there is a better way to do it?
SQLQuery query = session.createSQLQuery("
select {A.*},{B.*} from A_TABLE A left outer join B_TABLE B on A.QUOTE_ID = B.QUOTE_NUM ")
.addEntity("A", A_Class.class)
.addJoin("B", "A.bDocs");
for(Object result : query.list())
{
....
}
The mapping A file:
<class name="A_Class" table="A_TABLE" schema="S">
<id name="rowId" type="string">
<column name="ROW_ID" length="60" />
<generator class="assigned" />
</id>
<set name="BDocs" inverse="true" fetch="select" lazy="false">
<key>
<column name="QUOTE_NUM" length="60" not-null="true" />
</key>
<one-to-many class="B_Class" />
</set>
A_Class.java
public class A_Class implements java.io.Serializable
{
private String rowId;
private String QuoteId;
private Set BDocs= new HashSet(0);
// omitted all the set and get
}
The mapping B file:
<hibernate-mapping>
<class name="B" table="B_TABLE" schema="S">
<id name="rowId" type="string">
<column name="ROW_ID" length="60" />
<generator class="assigned" />
</id>
<many-to-one name="A" class="A_Class" fetch="select" lazy="false" outer-join="true" foreign-key="QuoteId" property-ref="QuoteId">
<column name="QUOTE_NUM" length="60" not-null="true" />
</many-to-one>
B_Class.java
public class B_Class implements java.io.Serializable
{
private String rowId;
private String quoteNum;
// omitted all the set and get
}
From this query i obtain 2 objects, one of A type and the other of B Type with a lot of correct datas but the set BDocs in the object of A type isn't filled. The goal is to get only the A Object with the variable BDocs filled with the B Objects.
I don't understand if the problem is in the query or in the mapping files. Anyone can help me?
Forgive me I am a newbie in NHibernate, I found some example in hbm.xml like below.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="test" >
<class name="test.FieldSetMapping" table="fieldsetmapping" discriminator-value="2352" lazy="false">
<id name="Id" column="fieldsetmapping_id" type="Int64">
<generator class="test.NHibernate.IdGenerator, test">
<param name="table">nextinstanceid</param>
<param name="column">next</param>
<param name="max_lo">9</param>
</generator>
</id>
<discriminator column="mapping_type" type="Int32" />
<version name="LastUpdateNumber" column="last_update_number" type="Int32" unsaved-value="-1"/>
<property name="OwnerName" column= "owner_name" type="String"/>
<component name="FieldSetDefinitionId" class="test.ObjectId">
<property name="InstanceId" column= "fieldsetdefinition_id" type="Int64"/>
</component>
<property name="OwnerTypeClassId" column= "owner_type" />
<bag name="FieldMappings" cascade="all-delete-orphan" generic="true" lazy="false">
<key column="fieldsetmapping_id" not-null="true" />
<one-to-many class="test.FieldSet.FieldMapping, test" />
</bag>
<property name="MappingHandlerClass" column="handler_class" />
</class>
<subclass name="test.EntityFieldSetMapping, test" discriminator-value="2353" extends="test.FieldSetMapping, test" lazy="false" >
<property name="TargetEntityType" type="test.Internal.NHibernate.ClassIdType, test" not-null="false">
<column name="target_entity_type"/>
</property>
</subclass>
<class ...>
...
</class>
<class ...>
...
</class>
</hibernate-mapping>
But I don't know what does discriminator mean . I check the Nhibernate Doc 5.1.6.
The <discriminator> element is required for polymorphic persistence
using the table-per-class-hierarchy mapping strategy and declares a discriminator
column of the table. The discriminator column contains marker values that tell
the persistence layer what subclass to instantiate for a particular row.A restricted
set of types may be used: String, Char, Int32, Byte, Short, Boolean, YesNo, TrueFalse.
Does it mean if the mapping_type > 2352 the NH will initialize the subclass test.EntityFieldSetMapping for the row of the table fieldsetmapping? thanks.
NHibernate will use the discriminator to detect which class needs to instantiate on a polymorphic scenario.
If mapping_type = 2352, it will create an instance of test.FieldSetMapping
if mapping_type = 2353, it will create an instance of test.EntityFieldSetMapping
Any other value should generate an exception.
I am getting an error in NHibernate.Collection.PersistentBag class when trying to load entities:
The value "MyProject.DomainModel.Operator" is not of type "MyProject.DomainModel.Operator" and cannot be used in this generic collection.
Notice that both value types are exactly the same. I've double-checked them in a comparer tool.
NHibernate is failing to add the value to a List collection at line bag.Add(element) .
The element variable is actually of type *object{DecoratorAopProxy_9cf850624c7e4ef9a8e2d9694bed26fd}*. I've noticed that the objects that can be successfully added to this list are of type object{MyProject.DomainModel.Operator}. This type is obtained from "quick watch" feature in VS2012 from the "Type" column.
Does anyone have an idea as to why NHibernate changes the type of this particular object to a proxy while others have pure entity types?
<class name ="PersonRole" table ="tblPersonRole" mutable ="false">
<id name="Id" column="PersonRoleID" type="Int32" access ="nosetter.lowercase-underscore">
<generator class="native"/>
</id>
<discriminator formula="case when RoleID in (2,4,5,6) THEN RoleID ELSE 0 END" />
<subclass discriminator-value="4" name="AccountManagerRole">
<bag name="Operators" >
<key column="OperatorID"></key>
<one-to-many class="BaseOperator"/>
<loader query-ref="LoadAllocatedOperators_ACCOUNTMANAGER"/>
</bag>
</subclass>
</class>
<class name="BaseOperator" table="tblOperator" lazy="true" >
<id name="Id" column="OperatorID" access ="nosetter.lowercase-underscore" type="Int32" unsaved-value="null">
<generator class="native" />
</id>
<discriminator column="OperatorType" type="string" />
<subclass discriminator-value ="OPR" name ="Operator" lazy="true">
<bag name="Customers" access="nosetter.camelcase-underscore" lazy="true" cascade="all-delete-orphan" inverse="true" fetch="join" >
<key column="OperatorId" />
<one-to-many class="MyProject.DomainModel.Customer, MyProject" not-found="ignore" />
</bag>
<subclass discriminator-value ="OPR2" name ="Operator2" lazy="true" />
</subclass>
</class>
So I do something like "select distinct accManager from AccountManagerRole accManager", which results in operators being loaded one at a time using their ID, and NHibernate crashes on one of them.
I've an issue using one-to-one mapping. I've searched internet and found many solutions but none was satisfying. Most of the examples carry overhead of storing parent instance in child class.
I want to use only parent Id in child class having foreign key constraint relationship but dont want to keep any parent instance in child.
When I try to load the records from database it throws exception "No row with the given identifier exists [AssemblyName.]". But, the record exists in Table "B" properly.
Any solutions for this issue?
The class structure:
class A {
public virtual string Id {get;set;}
public virtual B B {get;set;} // properties...... }
class B { public virtual string Id {get;set;} // properties......
public virtual string ParentId { get;set;} // class A Id }
The database structure:
CREATE TABLE [A](
[Id] [nvarchar](45) PRIMARY KEY
) ON [PRIMARY]
CREATE TABLE [B](
[Id] [nvarchar](45) PRIMARY KEY,
[ParentId] [nvarchar](45) NOT NULL
) ON [PRIMARY]
The mapping:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="A,AssemblyName" table="A" lazy="true">
<id name="Id" column="Id" type="string">
<generator class="assigned"/>
</id>
<one-to-one name="_B" cascade="all" fetch="join" foreign-key="None" constrained="true" class="B"/>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="B,AssemblyName" table="B" lazy="true">
<id name="Id" column="Id" type="string"> <generator class="assigned"/> </id>
<property name="_Name" column="Name"/> </class>
</hibernate-mapping>
One-to-one associations are always bidirectional in NHibernate. Mapping of class B is incomplete:
<class name="B,AssemblyName" table="B" lazy="true">
<id name="Id" column="Id" type="string">
<generator class="assigned"/>
</id>
<many-to-one name="A" unique="true" column="A" />
<property name="_Name" column="Name"/>
</class>
This is foreign key association. For more information see this detailed Ayende's blog post or NHibernate documentation.
Read this. A "real" one-to-one needs the same primary key in both tables (and no ParentId column).
I'm stuck trying to get the mapping I want to persist correctly. For my example, I have an ItemY class which can have 0,1,* Assets. However, an Asset can belong to an ItemY or an ItemZ object. I'm trying to use a cross-reference table to store this.
Schema
TABLE [dbo].[ItemY](
[ItemYID] [int] IDENTITY(1,1) NOT NULL,
--more columns here
TABLE [dbo].[Asset](
[AssetID] [uniqueidentifier] NOT NULL,
[AssetTypeID] [int] NOT NULL,
[DisplayOrder] [int] NOT NULL,
[Location] [varchar](255) NOT NULL,
TABLE [dbo].[ItemYAsset](
[ItemYID] [int] NOT NULL,
[AssetID] [uniqueidentifier] NOT NULL,
Mappings:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly" namespace="My.Namespace">
<class name="ItemY" table="ItemY">
<id name="ItemYId" column="ItemYID">
<generator class="identity" />
</id>
<bag name="Images" table="ItemYAsset" inverse="true" cascade="all-delete-orphan">
<key column="ItemYID" not-null="true" />
<many-to-many class="Asset" column="AssetID" unique="true" />
</bag>
<!--more mapping here-->
</class>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly" namespace="My.Namespace">
<class name="Asset" table="Asset">
<id name="AssetId" column="AssetID">
<generator class="guid.comb" />
</id>
<property name="DisplayOrder"></property>
<property name="Location"></property>
</class>
</hibernate-mapping>
I don't want to expose an ItemY property on Asset, since an Asset doesn't always belong to an ItemY. My ItemY class persists fine, and also persists the Asset class, but there is nothing added to the association table (ItemYAsset). Any idea what I'm doing wrong?
inverse="true" means the "other side" is responsible for persisting the relationship.
Since you have no "other side" (the relationship is unidirectional), remove that attribute.