I have been playing around trying to get mapping of 2 classes to 1
table in order to get lazy loading properties to work. I thought i'd
share it here. I posted a previous example but I have made som
improvements since. Before, I had to use a ISession.Refresh() between
inserting the first row to db and then update the blob field. This is
no longer neccesary. Let's start with an example:
I have a legacy database with a table called Invoice. It has 2 blobs
that contains xml data.
create table Invoice
(
InvoiceId int not null primary key,
InvoiceNo varchar(30),
CustomerName varchar(50),
XmlData1 varbinary(max),
XmlData2 varbinary(max)
)
What I had to do was to create 3 entity classes, 1 for the main
Invoice and 1 for each field that I want to lazy load:
public class Invoice
{
public int InvoiceId { get; set; }
public string InvoiceNo { get; set; }
public string CustomerName { get; set; }
public InvoiceXmlData1 XmlData1 { get; set; }
public InvoiceXmlData2 XmlData2 { get; set; }
Invoice()
{
XmlData1 = new InvoiceXmlData1();
XmlData2 = new InvoiceXmlData2();
}
}
public class InvoiceData
{
public int InvoiceId { get; set; }
public byte[] Data { get; set; }
}
public class InvoiceXmlData1 : InvoiceData
{
}
public class InvoiceXmlData2 : InvoiceData
{
}
The reason that I made one class per property is for the mapping to
work. The mapping looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-
lazy="true" assembly="Domain" namespace="Domain">
<class name="Invoice" table="Invoice">
<id name="InvoiceId">
<generator class="native"></generator>
</id>
<property name="InvoiceNo" not-null="true"></property>
<property name="CustomerName" not-null="false"></property>
<many-to-one name="XmlData1" column="InvoiceId" unique="true"
insert="false" update="false" cascade="none"></many-to-one>
<many-to-one name="XmlData2" column="InvoiceId" unique="true"
insert="false" update="false" cascade="none"></many-to-one>
</class>
<class name="InvoiceXmlData1" table="Invoice" >
<id name="InvoiceId">
<generator class="foreign">
<param name="property">Invoice</param>
</generator>
</id>
<property name="Data" column="XmlData1"></property>
</class>
<class name="InvoiceXmlData2" table="Invoice">
<id name="InvoiceId">
<generator class="foreign">
<param name="property">Invoice</param>
</generator>
</id>
<property name="Data" column="XmlData2"></property>
</class>
</hibernate-mapping>
Note cascade="none". cascade="save-update" would result i 2 inserts to
the same table. Also the attributes insert and update is set to
"false". I got IndexOutOfRangeException without these.
The code to insert:
Invoice inv = new Invoice();
inv.InvoiceNo = "12312";
inv.CustomerName = "The Customer";
inv.XmlData1.Data = new byte { 0x1, 0x2 };
session.Save(inv);
// assign newly created primary key to blob entities
inv.XmlData1.InvoiceId = inv.InvoiceId;
inv.XmlData2.InvoiceId = inv.InvoiceId;
// if data is null, only attach entity (small optimization, I think)
if (inv.XmlData1.Data == null)
session.Lock(inv.XmlData1, LockMode.None);
else
session.Update(inv.XmlData1);
if (inv.XmlData2.Data == null)
session.Lock(inv.XmlData2, LockMode.None);
else
session.Update(inv.XmlData2);
session.Flush();
updates works as usual:
Invoice inv = session.Get<Invoice>(...);
inv.XmlData1.Data = new byte { 0x2, 0x3 };
session.Flush();
Although I haven't tried deletes, but since cascade="none" it should
work. Just don't reference the blob entities after you deleted the
main entity. Maybe you need to do session.Evict(inv.XmlData1) to clear
the first level cache.
Comments?
Regards,
Johannes
On 14 Nov, 06:11, "Stefan Sedich" <[EMAIL PROTECTED]> wrote:
> No worries thanks Fabio, I still feel like an idiot for posting a
> wrong solution but hey I am only human :).
>
> Cheers
> Stefan
>
>
>
> On Fri, Nov 14, 2008 at 12:11 PM, Fabio Maulo <[EMAIL PROTECTED]> wrote:
> > Hi Stefan.
> > Thanks for the wiki in NHForge.
> > Only a note for who want write a wiki...
> > You can use WLW in your PC and than copy&paste the HTML.
> > 2008/11/13 Stefan Sedich <[EMAIL PROTECTED]>
>
> >> Back to a unique foreign key mapping with a many to one to get this to
> >> work :\, what I originally had but insisted on the one to one, this
> >> works fine.
>
> >> Updated my posts to reflect my failure :). Key for next time MAKE SURE
> >> I RUN ALL MY TESTS FIRST!!!
>
> >> Cheers
>
> >> On Fri, Nov 14, 2008 at 9:24 AM, Stefan Sedich <[EMAIL PROTECTED]>
> >> wrote:
> >> > Looks like this is an EPIC fail, inserts seem not to work :\, I
> >> > thought I had tried this but when I got to work this morning and re
> >> > ran my rest:
>
> >> > NHibernate.Id.IdentifierGenerationException: null id generated
> >> > for:NHibernateDocumentTest.DocumentFile
>
> >> > Looks like it is back to the drawing board.
>
> >> > Fun fun fun
>
> >> > On Thu, Nov 13, 2008 at 10:04 PM, Stefan Sedich
> >> > <[EMAIL PROTECTED]> wrote:
> >> >> Not a problem glad my heart ache might help someone in the future,
> >> >> look forward to contributing more.
>
> >> >> Cheers
>
> >> >> On Thu, Nov 13, 2008 at 10:00 PM, Tuna Toksöz <[EMAIL PROTECTED]>
> >> >> wrote:
> >> >>> Thanks, Stefan! We really appreciate your help on blogging.
>
> >> >>> On Thu, Nov 13, 2008 at 2:58 PM, Stefan Sedich
> >> >>> <[EMAIL PROTECTED]>
> >> >>> wrote:
>
> >> >>>> Ok whipped this one up just then :), hopefully it makes sense to
> >> >>>> someone
> >> >>>> else.
>
> >> >>>>http://weblogs.asp.net/stefansedich/archive/2008/11/13/lazy-loaded-on...
>
> >> >>>> Cheers
>
> >> >>>> On Thu, Nov 13, 2008 at 9:46 PM, Stefan Sedich
> >> >>>> <[EMAIL PROTECTED]>
> >> >>>> wrote:
> >> >>>> > Yep will be blogging about this tonight :), hopefully save someone
> >> >>>> > else some frustration. Infact I will do it right away.
>
> >> >>>> > On Thu, Nov 13, 2008 at 9:45 PM, Tuna Toksöz <[EMAIL PROTECTED]>
> >> >>>> > wrote:
> >> >>>> >> A post from you would be welcome ! :) hahaha :)
>
> >> >>>> >> On Thu, Nov 13, 2008 at 2:41 PM, Stefan Sedich
> >> >>>> >> <[EMAIL PROTECTED]>
> >> >>>> >> wrote:
>
> >> >>>> >>> Yep thanks Tuna the answer was there all along, supprised I only
> >> >>>> >>> found
> >> >>>> >>> this on 1 site :\ would have thought more people have
> >> >>>> >>> done/blogged
> >> >>>> >>> about this before.
>
> >> >>>> >>> Ohh well time for a beer.
>
> >> >>>> >>> Cheers
>
> >> >>>> >>> On Thu, Nov 13, 2008 at 9:38 PM, Tuna Toksöz <[EMAIL PROTECTED]>
> >> >>>> >>> wrote:
> >> >>>> >>> > From the forum, I see that
>
> >> >>>> >>> > But now imagine your B object may or may not have associated C
> >> >>>> >>> > (constrained="false"). What should getCee() return when
> >> >>>> >>> > specific B
> >> >>>> >>> > does
> >> >>>> >>> > not
> >> >>>> >>> > have C? Null. But remember, Hibernate must set correct value of
> >> >>>> >>> > "cee" at
> >> >>>> >>> > the
> >> >>>> >>> > moment it set B (because it does no know when someone will call
> >> >>>> >>> > getCee()).
> >> >>>> >>> > Proxy does not help here because proxy itself in already
> >> >>>> >>> > non-null
> >> >>>> >>> > object.
>
> >> >>>> >>> > So the resume: if your B->C mapping is mandatory
> >> >>>> >>> > (constrainted=true),
> >> >>>> >>> > Hibernate will use proxy for C resulting inlazy
> >> >>>> >>> > initialization. But
> >> >>>> >>> > if
> >> >>>> >>> > you
> >> >>>> >>> > allow B without C, Hibernate just HAS TO check presence of C at
> >> >>>> >>> > the
> >> >>>> >>> > moment
> >> >>>> >>> > it loads B. But a SELECT to check presence is just inefficient
> >> >>>> >>> > because
> >> >>>> >>> > the
> >> >>>> >>> > same SELECT may not just check presence, but load entire
> >> >>>> >>> > object. So
> >> >>>> >>> >lazy
> >> >>>> >>> >loadinggoes away.
>
> >> >>>> >>> > On Thu, Nov 13, 2008 at 2:34 PM, Stefan Sedich
> >> >>>> >>> > <[EMAIL PROTECTED]>
> >> >>>> >>> > wrote:
>
> >> >>>> >>> >> Final try:
>
> >> >>>> >>> >> <one-to-one name="DocumentFile" cascade="all-delete-orphan"
> >> >>>> >>> >>lazy="proxy" constrained="true" />
>
> >> >>>> >>> >> WORKS!!! Why is this the case can anyone shed some light why
> >> >>>> >>> >> constrained="true" on the Document worked?
>
> >> >>>> >>> >> On Thu, Nov 13, 2008 at 9:28 PM, Stefan Sedich
> >> >>>> >>> >> <[EMAIL PROTECTED]>
> >> >>>> >>> >> wrote:
> >> >>>> >>> >> > Arggggggggggg I was wrong this does not work. Seriously if I
> >> >>>> >>> >> > could
> >> >>>> >>> >> > throw NH out the window right now I would hehe. :\
>
> >> >>>> >>> >> > On Thu, Nov 13, 2008 at 9:25 PM, Fabio Maulo
> >> >>>> >>> >> > <[EMAIL PROTECTED]>
> >> >>>> >>> >> > wrote:
> >> >>>> >>> >> >> property lazynees is not supported in NH basically because
> >> >>>> >>> >> >> we
> >> >>>> >>> >> >> need
> >> >>>> >>> >> >> FieldInterceptors (AFIK not experimented in .NET)
>
> >> >>>> >>> >> >> 2008/11/13 codemonkey <[EMAIL PROTECTED]>
>
> >> >>>> >>> >> >>> Is this possible in NH? I have googled forever and cannot
> >> >>>> >>> >> >>> find
> >> >>>> >>> >> >>> any
> >> >>>> >>> >> >>> info at all? My only option it seems is to use a seperate
> >> >>>> >>> >> >>> table
> >> >>>> >>> >> >>> to
> >> >>>> >>> >> >>> my
> >> >>>> >>> >> >>> image and map using a one-to-one withlazyset tot true.
>
> >> >>>> >>> >> >>> Any advice would be good..
>
> >> >>>> >>> >> >>> Cheers
> >> >>>> >>> >> >>> Stefan
>
> >> >>>> >>> >> >> --
> >> >>>> >>> >> >> Fabio Maulo
>
> >> >>>> >>> >> > --
> >> >>>> >>> >> > Stefan Sedich
> >> >>>> >>> >> > Software Developer
> >> >>>> >>> >> >http://weblogs.asp.net/stefansedich
>
> >> >>>> >>> >> --
> >> >>>> >>> >> Stefan Sedich
> >> >>>> >>> >> Software Developer
> >> >>>> >>> >>http://weblogs.asp.net/stefansedich
>
> >> >>>> >>> > --
> >> >>>> >>> > Tuna Toksöz
>
> >> >>>> >>> > Typos included to enhance the readers attention!
>
> >> >>>> >>> --
> >> >>>> >>> Stefan Sedich
> >> >>>> >>> Software Developer
> >> >>>> >>>http://weblogs.asp.net/stefansedich
>
> >> >>>> >> --
> >> >>>> >> Tuna Toksöz
>
> >> >>>> >> Typos included to enhance the readers attention!
>
> >> >>>> > --
> >> >>>> > Stefan Sedich
> >> >>>> > Software Developer
> >> >>>> >http://weblogs.asp.net/stefansedich
>
> >> >>>> --
> >> >>>> Stefan Sedich
> >> >>>> Software Developer
> >> >>>>http://weblogs.asp.net/stefansedich
>
> >> >>> --
> >> >>> Tuna Toksöz
>
> >> >>> Typos included to enhance the readers attention!
>
> >> >> --
> >> >> Stefan Sedich
> >> >> Software Developer
> >> >>http://weblogs.asp.net/stefansedich
>
> >> > --
> >> > Stefan Sedich
> >> > Software Developer
> >> >http://weblogs.asp.net/stefansedich
>
> >> --
> >> Stefan Sedich
> >> Software Developer
> >>http://weblogs.asp.net/stefansedich
>
> > --
> > Fabio Maulo
>
> --
> Stefan Sedich
> Software Developerhttp://weblogs.asp.net/stefansedich
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---