-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: (basic question) foreign-key nullables and object creation
PostPosted: Thu Nov 10, 2005 6:24 pm 
Hi, this question is kind of topic since it involves db modeling and asp.net code, but applies to NHibernate since it involves how I create my hql files.

If I have a one-to-one, say Customer -> Wishlist in my Customerc# code, which is best?

public Wishlist Wishlist
{
get { return _wishlist; }
}

or

public Wishlist Wishlist
{
get
{
if (_wishlist == null)
{
_wishlist = new Wishlist();
}
return _wishlist;
}

The second version is nice since I don't get runtime errors if I try to access wishlist without first instantiating it explicitly.

However, the problem is that when I select a Customer though NHiberate, it accesses the Wishlist property and creates a new Wishlist. Now, since this is an empty wishlist, if I have non-null columns in my Wishlist table, I get an error.

So, is the solution to initialize all the Wishlist's fields in its constructor? Is this best practise?

Also, I've read that it's bad to have nullable foreign key constraints. Under the first example, I would have that, right? I.e. a Customer wouldn't necessarily have a Wishlist. So, the does the rule for not having nullable foreign key constraints imply that the entire object graph should be created in the DB when the base object is created?

So, I guess the ultimate question is: should I initialize all an object's fields upon it's creation in the constructor? This implies when using NHiberate creating the entire object graph when the object is created. Is this okay or too much work if I want things lazy loaded?


Top
  
 
 Post subject:
PostPosted: Fri Nov 11, 2005 7:31 pm 
Contributor
Contributor

Joined: Thu May 12, 2005 8:45 am
Posts: 226
You should initialize all fields that don't default to their "unsaved-value". For example:
Code:
...
private int age;
private string fname;
private string lname;
private DateTime birthdate;
...

Integers initialize to 0, strings to null, and DateTime to DateTime.MinValue. So, if Age has an "unsaved-value" of 0, don't worry about that one. If LastName (lname) is NOT-NULL in the DB, then you should initialize it to something.

Clear as mud? That doesn't seem like a good example, but I'm tired and that's all that comes to mind.

That's not a rule that's written in stone, just what makes sense to me at the moment.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 14, 2005 7:58 am 
Beginner
Beginner

Joined: Mon Oct 03, 2005 4:59 am
Posts: 26
Location: Cambridge, UK
I'm not clear on exactly what to do in the default constructor either. Initially I was using code like this, because that's what k-dub's MyGeneration template produced:
Code:
class Parent
{
    private int m_id;
    private IList m_children;
    private Address m_address;

    public Parent()
    {
        m_id = 0;       
        m_name = String.Empty;
        m_children = new ArrayList();
        m_address = new Address();
    }
    //...
}


That worked fine, until I had a need for a bidirectional one-to-one relationship. Obviously this didn't work:
Code:
class A
{
    private B m_b;

    public A()
    {
        m_b = new B();
    }
}

class B
{
    private A m_a;

    public B()
    {
        m_a = new A();
    }
}
...
A a = new A();    //Stack overflow!


At that point I read all the documentation I could find, trying to figure out what to do in these default ctors. All the examples in the NHibernate and Hibernate 2.1 docs use implicit default ctors, so I concluded it would be fine to just leave all entity object references and collections null, trusting NHibernate to initialize them properly:
Code:
class Parent
{
    private int m_id;
    private string name;
    private IList m_children;
    private Address m_address;

    public Parent()
    {
        m_id = 0;
        m_name = String.Empty;
        m_children = null;
        m_address = null;
    }
    //...
}


Unfortunately, I already had lots of code around like this:...
Code:
    if( parent.Children.Count > 0 )
         // Do something

...which was now producing null reference exceptions. This surprised me; I thought from the docs ("Due to the underlying relational model, [collections] do not support null value semantics; Hibernate does not distinguish between a null collection reference and an empty collection.") that NHibernate would instantiate an empty collection. I guess not. So now my default ctors look like this:
Code:
class Parent
{
    private int m_id;
    private string name;
    private IList m_children;
    private Address m_address;

    public Parent()
    {
        m_id = 0;
        m_name = String.Empty;
        m_children = new ArrayList();
        m_address = null;
    }
    //...
}

Nulls for entity object references, empty collections for collection properties, defaults (or unsaved-value, if that's different) for everything else. That seems to work for me so far, but I wish I had a better understanding of why.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 14, 2005 10:43 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
IMO, your problem is more related to the way you handle your associations...

If the adress can not be null, you shoud either create it in the ctor or make sure that it is set as soon as possible (for the one-to-one issue).

Note that you may add a public constructor taking the association (to be sure that it is never null) and a protected constructor taking nothing for NHibernate.
AFAIK, It should work well as long as you never save an entity with a null association... (and it shouldn't be allowed).

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 15, 2005 7:16 am 
Beginner
Beginner

Joined: Mon Oct 03, 2005 4:59 am
Posts: 26
Location: Cambridge, UK
NHibernate can use a protected default constructor, even when the class is not lazy loaded? That's good to know.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.