Freitag, 15. Juni 2007

One-to-one mapping and Lazy loading

Often we have the following situation: An entity has some attributes that are important and often accessed and then it has some other attributes that are either rarely used or their content is large in size (e.g. a photo or a document). In such situations it is common to split the entity into two tables. One table containing the important attributes and the other the remaining ones. A typical example is table 'Person' and table 'PersonDetails'. These tables are relatet by a 1 to 0..1 relation. That is a person can have person details but doesn't need to. On the other hand 'person details' always belong to a 'person'.

Question: How can we instruct NHibernate and/or ActiveRecord to give us such a relation. We want to have the possibility to load a list of persons WITHOUT loading also their corresponding details. The details should ONLY be loaded when we really access them. That is called 'Lazy Loading'.

Just using a one-to-one relation doesn't work! We have to use a 'trick' and use a combination of a many-to-one and a one-to-one relation. This solves our problem.

NHibernate

Let us look at the code:

namespace NHibernateTest
{
    public class Person
    {
        private int _personID;
        private string _lastName;
        private string _firstName;
        private PersonPhoto _photo;

        public virtual int PersonID
        {
            get { return _personID; }
            set { _personID = value; }
        }

        public virtual PersonPhoto Photo
        {
            get { return _photo; }
            set { _photo = value; }
        }

        public virtual string LastName
        {
            get { return _lastName; }
            set { _lastName = value; }
        }

        public virtual string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }
    }

    public class PersonPhoto
    {
        private int _personID;
        private byte[] _photo;
        private Person _owner;

        public virtual int PersonID
        {
            get { return _personID; }
            set { _personID = value; }
        }

        public virtual Person Owner
        {
            get { return _owner; }
            set { _owner = value; }
        }

        public virtual byte[] Photo
        {
            get { return _photo; }
            set { _photo = value; }
        }
    }
}

and now at the NHibernate mapping file(s)

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateTest" namespace="NHibernateTest">
  <class name="Person" >
    <id name="PersonID" type="Int32">
      <generator class="identity" />
    </id>
    <property name="LastName" type="String" length="50" />
    <property name="FirstName" type="String" length="50" />
    <many-to-one name="Photo" class="PersonPhoto" />
  </class>

  <class name="PersonPhoto">
    <id name="PersonID" type="Int32">
      <generator class="foreign">
        <param name="property">Owner</param>
      </generator>
    </id>
    <property name="Photo" type="BinaryBlob" />
    <one-to-one name="Owner" class="Person" constrained="true" />
  </class>
</hibernate-mapping>

Note:

  • on the "parent" side (Person) we have the many-to-one relation which points to PersonPhoto.
  • on the "child" side (PersonPhoto) the primary key (PersonID) is the same as on the "parent" side. Thus the value must be "inherited" from the parent. This is the reason to use "foreign" as generator class. The <param> tag just points to the Property from which NHibernate can get this PK value, in our case the property is called Owner (which is the Person who owns this photo).
  • on the "child" side we have the one-to-one relation which points to Person.
  • the one-to-one relation sets constrained=true since the person details belongs to a person (a person MUST exists).

ActiveRecord

We can define the same behaviour in ActiveRecord. Here I choose a similar sample as above, a one-to-one relation between a Car and its CarPhoto. Code explains better than many words, thus:

[ActiveRecord("Car", Lazy = true)]
public class Car : ActiveRecordBase<Car>
{
    private Guid _CarID;
    private CarPhoto _photo;
    private string _make;

    [PrimaryKey(PrimaryKeyType.Guid, "CarID", ColumnType = "Guid")]
    public virtual Guid CarID
    {
        get { return _CarID; }
        set { _CarID = value; }
    }

    [BelongsTo(Column = "CarID", Unique = true)]
    public virtual CarPhoto Photo
    {
        get { return _photo; }
        set { _photo = value; }
    }

    [Property(ColumnType = "String", Length = 50)]
    public virtual string Make
    {
        get { return _make; }
        set { _make = value; }
    }
}

[ActiveRecord("CarPhoto", Lazy = true)]
public class CarPhoto : ActiveRecordBase<CarPhoto>
{
    private Guid _CarID;
    private Car _owner;
    private byte[] _photo;

    [PrimaryKey(PrimaryKeyType.Foreign, "CarID", ColumnType = "Guid")]
    public virtual Guid CarID
    {
        get { return _CarID; }
        set { _CarID = value; }
    }

    [OneToOne(Constrained = true)]
    public virtual Car Owner
    {
        get { return _owner; }
        set { _owner = value; }
    }

    [Property(ColumnType = "BinaryBlob", SqlType = "VARBINARY(MAX)")]
    public virtual byte[] Photo
    {
        get { return _photo; }
        set { _photo = value; }
    }
}

Now I can happily load a list of cars and the photos are not loaded by default but only when I really access them...

45 Kommentare:

Anonym hat gesagt…

This doesnt seem to work because the many-to-one on person will look for a column named photo in the person table. Did you miss something?

Billy hat gesagt…

Excellent post, thanks.

Anonym hat gesagt…

I had the same problem as the first poster. I fixed the problem by doing this:

many-to-one name="Photo" column="PersonID" class="PersonPhoto" unique="true"

Anonym hat gesagt…

Hi all
my name is Tom and im completely new to this forum.

I hope that I'll learn and share a lot of interesting things.


Thanks!

Anonym hat gesagt…

Hallo.
Ich mochte mit Ihrer Website gnschenker.blogspot.com Links tauschen

Alex hat gesagt…

Great! That did the trick! Thanks!

P.S. Anonymous is right - 'column' is required in the many-to-one mapping to make it work.

Anonym hat gesagt…

[url=http://huavitipwill.chez.com/?c=3&p=590]short dress hot legs[/url] - How does he come up with such stunning creations?This is an Egyptian girl going to the village these are the things I like to think when I do shoes, make up these silly romantic things, he said.
The company I bought it from assured me they would disappear within a couple of days but a week later they were still there.

[url=http://patmivisu.chez.com/19/cougar-brand-shoes.php]cougar brand shoes[/url] - i would have said the PT is probably lighter, then i noticed the one you are showing has GH, so it will be about the same weight.... [url=http://nabwirasbui.chez.com/?c=3&p=580]welly shoes[/url] . navy dinner dress blue uniforms wendy bates dvm go barefoot aloha shirts design a bridesmaid dress sewing pattern how do jamaicans dress

Anonym hat gesagt…

I love your site, but honestly tell you that you need more for him to monitor those who commented with your records

Anonym hat gesagt…

hey, nice weblog and good publish

Anonym hat gesagt…

Hello, you site is very funny he told me to cheer up .. Merry Christmas.

Anonym hat gesagt…

Did you people notice that the main character is a girl in this game? Interested to see how that plays how.
[url=http://insurancefull.com]Full insurance[/url]

Anonym hat gesagt…

ab?ad?b

Anonym hat gesagt…

I refuse.

Anonym hat gesagt…

SlimFast is an all-natural weight loss supplement. It contains a proprietary mix of herbal ingredients that work to increase metabolism, burn fat, and safely suppress appetite. Unlike some other weight loss products, SlimFast does not contain any harmful chemicals or substances.

Anonym hat gesagt…

Good job!

Anonym hat gesagt…

Merry Christmas and Happy New Year, may all your wishes come true!

Anonym hat gesagt…

NOW YOU CAN PERFORM LIKE A YOUNG LIONONCE AGAIN!

It’s true: we’re all getting older. And while some say age is all in the mind, it does sometimes show

in the body — when you can’t seem to perform the same in the bedroom as you used to. Now there’s

Excel, an all-natural solution to your woes between the sheets.

We’ve carefully blended a proven mix of herbs that will take years off your age, letting you perform

in bed like the young lion you once were. You’ll feel like you’re back in your 20s — or even younger —

after taking Excel for just a few short weeks. And renewed sexual prowess won’t be your only benefit:

you’ll also feel less anxious, more relaxed, and healthier overall, thanks to the bonus properties of

our 100% pesticide-free herbal ingredients. Some of our ingredients, long used as aphrodisiacs around

the world, even intensify the pleasure you feel at your partner’s touch. Imagine all of these benefits

— with no side effects to speak of!

Anonym hat gesagt…

Misoprostol tablet
What is this medicine?

MISOPROSTOL helps to prevent stomach ulcers in patients using nonsteroidal antiinflammatory drugs (NSAIDS, drugs commonly used for arthritis, inflammation, and pain). Misoprostol reduces the amount of acid produced in the stomach and protects the stomach lining from the effects of acid.

Anonym hat gesagt…

Good article!!!

Anonym hat gesagt…

Xanax (Alprazolam) is used to treat anxiety disorders and panic attacks. Alprazolam is in a class of

medications called benzodiazepines. It works by decreasing abnormal excitement in the brain. Unlike

other benzodiazepines which must be taken several times a day, Xanax is a once-daily formula, helping

you all day long.

Anonym hat gesagt…

Merry Christmas! Let the new year will bring a lot of money

Anonym hat gesagt…

Good sait, its very interesting//

Anonym hat gesagt…

Good Article

Anonym hat gesagt…

Interesting posti for me//

Anonym hat gesagt…

moving time watches ny Graham replica watch | Dolce & Gabbana, Glashutte fake gucci watches

Anonym hat gesagt…

Interesting for)) ff

Anonym hat gesagt…

Beautiful post, great ))

Anonym hat gesagt…

Good article. Thank you.
http://valium.blog.com/2011/01/04/buy-valium-online

Anonym hat gesagt…

Good Article

Anonym hat gesagt…

Mm, its fantastic-/

Anonym hat gesagt…

Good article. Thank you.
http://sonniksnet.blog.com/2011/01/08/order-mefenorex

Anonym hat gesagt…

I got a real pleasure reading you.

Anonym hat gesagt…

Awesome, that’s exactly what I was scanning for! You just spared me alot of searching around

Anonym hat gesagt…

Good article. Thank you
http://ordererimin.putblog.com/2011/01/10/4/

Anonym hat gesagt…

kiev escort girls ))

Anonym hat gesagt…

mtv 2010awards

Hello

Wir stimmen wieder absolut nicht überein mit der diesjährigen mtv awards Entscheidung.

Bitte geht zu unsere kleine Web Abstimmung

http://micropoll.com/t/KEcJnZBNrh


Lady Gaga kann doch wirklich nicht besser sein als Sting

Diese Umfrage wird unterstützt von MTVawards 2010 sponsor femmestyle
[url=http://www.femmestyle.ch]brustvergrößerung plastische Chirurgie[/url]


Nächstes mal muss wieder unbedingt um einiges besser werden.

Anonym hat gesagt…

Растаможка Киев, Одесса
Консультации ВЭД
Дима Литейный
logisticskiev7@yandex.ru
+38 093 318 1567

Anonym hat gesagt…

I am not sure why I have come to love swarovski so much maybe because it is Austrian and I love Austria!


[url=http://www.buyswarovski.net/ringe.html]swarovski ringe[/url]

Anonym hat gesagt…

Servus!

Was fuer eine WM! Koennt ihr euch vorstellen, dass die Schweiz immer besser als Oesterreich sein wird?

Bitte besucht unsere nette Umfrage.

http://micropoll.com/t/KENMDZBJU1

Mit freundlicher Unterstuetzung von finanzoptimieren.
[url=http://www.finanzoptimieren.com]lebensversicherung rente[/url]

Die Weltmeisterschaft ist auf jedenfall jetzt schon besser als Frankreich 1998!

Anonym hat gesagt…

オンラインカジノ ボーナス happiness. "Yes, sire," replied St. Luc. http://xn--japan-ym4dobj1jwjxk6dc.com/ オンラインカジノ 詐欺 pensa le qui, avait rendu souhait. オンラインカジノ ボーナス [url=http://is.gd/TdvUSV ]オンラインカジノ 比較 [/url]toujours faisant une vigoureuse résistance. Philippe de Montfort vint

Anonym hat gesagt…

top [url=http://www.001casino.com/]free casino games[/url] hinder the latest [url=http://www.casinolasvegass.com/]las vegas casino[/url] manumitted no consign perk at the foremost [url=http://www.baywatchcasino.com/]free gratuity casino
[/url].

Anonym hat gesagt…

Hey! I know this is kind of off topic but I was wondering if
you knew where I could find a captcha plugin for my comment form?
I'm using the same blog platform as yours and I'm having
problems finding one? Thanks a lot!

Here is my homepage :: guaranteed issue life insurance

Anonym hat gesagt…

hi!,I love your writing so a lot! share we be in contact extra approximately your post on AOL?

I need a specialist on this house to solve my problem.
May be that's you! Looking ahead to peer you.

Review my weblog; gourmet coffee beans

Anonym hat gesagt…

Hi! This is my 1st comment here so I just wanted to give a
quick shout out and tell you I really enjoy reading
your blog posts. Can you recommend any other blogs/websites/forums that deal
with the same subjects? Thank you!

My web blog ... org.ar

Anonym hat gesagt…

Great post. I was checking continuously this weblog and I'm impressed! Very useful info specially the ultimate phase :) I take care of such information a lot. I was seeking this particular info for a long time. Thanks and best of luck.

Also visit my webpage; click the up coming internet site