NHibernate tries to create the same entity twice - c#

Currently I have database with the following associations:
One Client to Many Intakes
One Intake to Many CaseManagements
One CaseManagement to Many Interventions
Client, Intake, CaseManagement are single classes per table
Intervention is a class-hierarchy-per-table.
Currently, if I do something like this:
var client = new Client();
clientRepo.Add(client);
var intake = new Intake();
client.Add(intake);
var caseMan = new CaseManagement();
intake.Add(caseMan);
clientRepo.Update(client);
Everything works fine, and NHibernate creates a Client, then an Intake and then a CaseManagement in the database (all appropriately linked).
However, if do the following:
var client = new Client();
clientRepo.Add(client);
var intake = new Intake();
client.Add(intake);
var caseMan = new CaseManagement();
intake.Add(caseMan);
var intervention = new SubIntervention();
caseMan.Add(intervention);
clientRepo.Update(client);
It screwed up and runs the following SQL:
INSERT INTO TblClient ... (*)
INSERT INTO TblIntake ...
INSERT INTO TblCaseManagement ...
INSERT INTO TblClient ... (*)
Where the starred lines are identical. I have no clue why using inheritance is causing this.
Here is my mapping for my Intake class (which is pretty much the same as Client and CaseManagement).
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="WebTracker4"
namespace="WebTracker4.Domain">
<!-- Class Mapping -->
<class name="Intake" table="TblIntake">
<!-- Id -->
<id name="Id" column="IntakeId">
<generator class="sequence">
<param name="sequence">IntakeSequence</param>
</generator>
</id>
<!-- TCN -->
<version name="Tcn" column="IntakeTcn" type="Int64" />
<!-- Client -->
<many-to-one name="Client" column="ClientId" class="Client" />
<!-- Case Management -->
<bag name="CaseManagements" inverse="true" cascade="all" table="TblCaseManage" order-by="CaseManageId desc">
<key column="IntakeId" />
<one-to-many class="CaseManagement" />
</bag>
<!-- Properties -->
...
</class>
</hibernate-mapping>
Here's my mapping for the Intervention class hierarchy:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="WebTracker4"
namespace="WebTracker4.Domain.Interventions">
<!-- Class Mapping -->
<class name="Intervention" table="TblIntervention" abstract="true">
<!-- Id -->
<id name="Id" column="InterventionId">
<generator class="sequence">
<param name="sequence">InterventionSequence</param>
</generator>
</id>
<!-- Discriminator -->
<!-- This is used so that we can have Intervention subclasses. -->
<discriminator column="InterventionType" type="String" />
<!-- TCN -->
<version name="Tcn" column="InterventionTcn" type="Int64" />
<!-- Case Management -->
<many-to-one name="CaseManagement" column="CaseManageId" class="WebTracker4.Domain.CaseManagement, WebTracker4" />
<!-- Properties -->
....
<!-- Assessment Subclass -->
<subclass name="SubIntervention" discriminator-value="Sub">
...
</subclass>
</class>
What am I missing that is making it try to re-add the Client entity? What also may be of note is that if I screw up the column names in the subclass, NHibernate doesn't say anything.
This is driving me crazy, please help :)

I figured out the problem. It was because I was using the InterventionType column as both the discriminator and a property. I found that if I changed
<discriminator column="InterventionType" type="String" />
into
<discriminator column="InterventionType" type="String" insert="false" />
the problem went away.
I think it's because you're basically telling NHibernate not to manage the discriminator column.

Related

ORA 01407 - Error - Cannot update to NULL

My problem is that i have two entities (Document and Attach) that has an relationship one-to-one. In my app, i can save first the Document and lately if i want, i can attach an archive to it, that will be on the table Attach.
The error occurs when i have an object Document already inserted in database and then i try to add an attach on it.
Below is the nhibernate mapping:
Document.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Sigre.Business"
namespace="Sigre.Business.BusinessEntity">
<class name="Document" lazy="false" table="grsds.documento_fcdr">
<id name="Code" type="int" unsaved-value="0" column="docf_sq_documento_fcdr">
<generator class="sequence">
<param name="sequence">grsds.sq_docf_sq_documento_fcdr</param>
</generator>
</id>
<property name="Nome" type="AnsiString" length="100" not-null="true" column="docf_nm_documento_fcdr" />
<many-to-one name="Manifest" class="TransportManifest" column="mtra_sq_manifesto_transporte" not-null="false" cascade="none" />
<many-to-one name="User" class="User" column="user_id" not-null="false" cascade="none" />
<set name="Attach" inverse="false" lazy="false" cascade="save-update">
<key column="docf_sq_documento_fcdr" />
<one-to-many class="Attach" />
</set>
</class>
</hibernate-mapping>
Attach.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Sigre.Business"
namespace="Sigre.Business.BusinessEntity">
<class name="Attach" lazy="false" table="grsds.espec_documento_fcdr">
<id name="Code" type="int" unsaved-value="0" column="docf_sq_documento_fcdr">
<generator class="foreign">
<param name="property">Document</param>
</generator>
</id>
<property name="Archive" column="esdf_mm_documento_fcdr" type="BinaryBlob" not-null="true" />
<one-to-one constrained="true" name="Document" access="property" />
</class>
</hibernate-mapping>
If i am inserting both Document and Attach together, it works. But when i have a Document created and try to insert an Attach, the following error occurs:
ORA-01407: cannot update ("GRSDS"."ESPEC_DOCUMENTO_FCDR"."DOCF_SQ_DOCUMENTO_FCDR") to NULL
What i tried:
1 - Save the Document having the attach to insert:
bmDocument.Save(document);
Ok i solved this question.
When i bring the object Document from database, the attribute Attach when has no Attach, come as an empty list: {}
When i tried to add an Attach to this Document, i was overwriting the reference, like this:
Document.Attach = new List() { new Attach() };
The solution was use the method Add of the list that was brought from the database:
Document.Attach.Add( new Attach() );

Need help with simple NHibernate mapping

Need help with a simple NHibernate relationship...
Tables/Classes
Request
-------
RequestId
Title
…
Keywords
-------
RequestID (key)
Keyword (key)
Request mapping file
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="CR.Model" assembly="CR">
<class name="CR.Model.Request, CR table="[dbo].[Request]" lazy="true">
<id name="Id" column="[RequestID]">
<generator class="native" />
</id>
<property name="RequestorID" column="[RequestorID]" />
<property name="RequestorOther" column="[RequestorOther]" />
…
Keyword??
</class>
</hibernate-mapping>
How do I simply map multiple keywords to a request? I don't need another mapping file for the keyword class, do I?
It's be great if I could not only get the associated keywords, but add them too...
You'll need a set (or some other kind of collection mapping, but I think a set is the best-fit).
check this

How to map Image type in NHibernate?

I have at my SQL Server 2000 Database a column with type Image. How can I map it into NHibernate?
We used BinaryBlob on the mapping config file, and byte[] on the property.
Below is the sample code that i have used to map an image field. Where BlogImage was a column of Image Datatype mapped to byte type property BlogImage. length="2147483647" was used to ensure copy of full image in to database as nhibernate some times limit the max size of data that is going to be inserted.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="EAS.MINDSPACE.Infrastructure.Business.Entities.BlogMaster,EAS.MINDSPACE.Infrastructure.Business.Entities" lazy="false" table="BlogMaster" schema="dbo" >
<id name="BlogId" column="BlogId">
<generator class="native" />
</id>
<property name="BlogData" column="BlogData" />
<property name="BlogImage" column="BlogImage" length="2147483647" />
<property name="UserId" column="UserId" />
<property name="CreatedByName" column="CreatedBy" />
<property name="CreatedOn" column="CreatedOn" />
<property name="ReplyCount" column="ReplyCount" />
</class>
</hibernate-mapping>
NHibernate 3.x does all the magic it self.
Sql:
Create table tblCompany (..., Logo image);
NHibernate-Mapping (important to set length!!!):
<class name="Company"
table="tblCompany">
...
<property name="_logo"
column="Logo"
not-null="false"
length="2147483647"
access="field" />
...
</class>
C#-Class:
public class Company {
...
private Image _logo;
...
}

Joining NHibernate Classes that share a common column but no foreign key

I have a couple of tables that I want to map to classes. The tables look like this:
Asset
---------
AssetId
AssetName
Product
---------
ProductId
ProductName
AssetId
Disposal
---------
DisposalId
AssetId
DisposalDate
Basically what I want to do is join the Product Table to the Disposal table on AssetId so that my Product has a collection of Disposals joined by asset. I have defined the following mapping but NHibernate (1.2) seems to ignore the key column defined in the bag and chooses to join the Product table to the Disposal table by ProductId (ie Product.ProductId = Disposal.AssetId). I'm not sure if this is a bug or if I'm not defining it properly but if anyone has a way to do this I'd be most greatful.
<class name="Product" table="Product" lazy="false">
<id name="ProductId" column="ProductId" type="int">
<generator class="native" />
</id>
<property name="ProductName" column="ProductName"/>
<bag name="Disposals" fetch="join" >
<key column="AssetId" foreign-key="AssetId/>
<many-to-many class="Disposal"/>
</bag>
</class>
Have you got your Disposals mapped to Products?
Your schema doesn't unique relate a Disposal to a Product. A Disposal can only relate to an Asset, not a Product.
You schema says to me that an Asset has many Products, and an Asset has many Disposals. There's nothing that says a Disposal is for a particular product.
The clean way:
<class name="Product" table="Product" lazy="false">
<id name="ProductId" column="ProductId" type="int">
<generator class="native" />
</id>
<property name="ProductName" column="ProductName"/>
<many-to-one name name="Asset" class="Asset" column="AssetId" />
</class>
<class name="Asset">
<id name="AssetId" >
<generator class="native" />
</id>
<property name="AssetName" />
<bag name="Disposals">
<key column="AssetId" />
<many-to-many class="Disposal" />
</bag>
</class>
foreign-key is used for DDL, I think it is the name of the foreign key constraint generated by schema export.
You can try property-ref, not completely sure if it works:
<class name="Product" table="Product" lazy="false">
<id name="ProductId" column="ProductId" type="int">
<generator class="native" />
</id>
<property name="ProductName" column="ProductName"/>
<property name="AssetId" />
<bag name="Disposals" fetch="join" >
<key column="AssetId" property-ref="AssetId/>
<one-to-many class="Disposal"/>
</bag>
</class>

How to use a child object field as part of the compound key in another child in NHibernate

I need to create a new Many-To-One relationship on my User entity which joins against another entity. The problem is the other entity has a compound key of which 1 field is a field in the User entity and the other is a field in another Many-To-One entity.
User.Key -> User.NewThing.Key
User.SubThing.Key -> User.NewThing.Key
Below is the invalid mapping file I am ideally wanting to use where JeanieUserTyped is my newthing and the ApplicationId is the key in question which comes from ShortCode.ApplicationId.
Question is how do I tell it to map the application part of the compound key?
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="JeanieMaster.Domain.Entities" assembly="JeanieMaster.Domain">
<class name="JeanieUser" table="DBSVR1.Jeanie_Master.dbo.JeanieUser" select-before-update="false" optimistic-lock="none">
<id name="Id" column="UserId" type="Int32">
<generator class="identity"/>
</id>
<property name="Mobile" type="String"/>
<property name="UniqueReoccurBillingRefId" type="String"/>
<property name="DateJoined" type="DateTime"/>
<property name="IsActive" type="Boolean"/>
<many-to-one name="MobileNetwork" class="MobileNetwork" column="MobileNetworkId" />
<many-to-one name="ShortCode" class="ShortCode" column="ShortCodeId" />
<many-to-one name="MobileHandset" class="MobileHandset" column="HandsetId" />
<many-to-one name="JeanieUserTyped" class="JeanieUserTyped">
<column name="Mobile" />
<column name="ApplicationId" />
</many-to-one>
</class>
</hibernate-mapping>
Can you give more details, sounds like you have 3 entities,
User
SubThing
NewThing
Where NewThing resolves a Many-to-Many with User and SubThing - am I close?
Maybe like this:
User -< SubThing
| |
/\ /\
NewThing
I don't suppose the composite key stuff in nhibernate is relevant?

Categories

Resources