Navigation Property vs Id Field

7 posts, 2 answers
  1. Chuck
    Chuck avatar
    30 posts
    Member since:
    Sep 2010

    Posted 12 Apr 2012 Link to this post

    Does it make any difference to use one or the other?  For example:

    Parent: Id
    Child: Id, ParentId  (navigation property Parent created automatically)
     
    myChild.Parent = myParent
     
    vs.
     
    myChild.ParentId = myParent.Id
  2. Answer
    Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 17 Apr 2012 Link to this post

    Hello Chuck,

    In short: using the navigation property is the preferred method of setting relationship values.  

    There is one important difference between these two approaches - there is no convenient way to handle creation of the whole object sub-tree using the foreign key property.

    To illustrate the case imagine the following scenario:
    class Customer
    {
        int Id;
        string FirstName;
        string LastName;
        int AddressId;
        Address Address;
    }
     
    class Address
    {
        int Id;
        string City;
        string Street;
    }

    When you create a new customer you should create a new instance of address too.

    If you use the navigation property setter your code should do these steps:
    1. Create new Customer instance, add it to the context.
    2. Create new Address instance, set newly created customer's address navigation property to the new address instance and add the address instance to the context.
    3. Call SaveChanges method of the context

    If you use the "raw" foreign key property setter the code should include the following steps:
    1. Create new Address instance, add it to the context.
    2. Call SaveChanges method of the context in order to get the ID of the new address instance.
    3. Create new Customer instance, add it to the context.
    4. Set the customer's AddressId to the ID of the address instance.
    5. Call SaveChanges method of the context.

    As you see using the "raw" foreign key property in this scenario will make the things a bit complicated because you do not know the ID of the newly created address instance and have to obtain it first before assigning in to the customer. If you use the navigation property the issue is solved easily using simple assignment - OpenAccess will take care of the plumbing required.

    In case you are linking a look-up table or a record that is already loaded in OpenAccess context you can use either one of the approaches.

    Let us know if you need any clarifications.
     
    Kind regards,
    Viktor Zhivkov
    the Telerik team
    Telerik OpenAccess ORM Q1 2012 release is here! Check out what's new or download a free trial >>
  3. DevCraft banner
  4. Chuck
    Chuck avatar
    30 posts
    Member since:
    Sep 2010

    Posted 17 Apr 2012 Link to this post

    That answers my question.  Thank you very much.
  5. Answer
    TSE
    TSE avatar
    381 posts
    Member since:
    Sep 2008

    Posted 18 Apr 2012 Link to this post

    Hi Chuck,

    As an addition to the answer from Viktor you should be aware that when you use the "raw" way of setting the id, you issue a call to SaveChanges() twice. Thus you actually do a database Commit twice.
    So lets assume that the first creation of the Address is done without errors, but the second creation of the Customer goes wrong. Doing so it doesn't matter if you do a rollback, since you already Committed the first change (the Address)... so you will have an Address instance hanging around forever.

    When doing it the "navigation" way (the right way in my opinion) you only issue one call to SaveChanges thus only one database Commit...so if anything goes wrong you can just rollback the changes and you will be at the point where you started your transaction again.
    I use a pattern like the below for doing manipulations on the model:

    try
    {
        // Explicit start the transaction if it has not been started yet

       // Do your model manipulation

      // Call SaveChanges (Commit)

    }
    catch (Exception e)
    {
       // Rollback changes
    }

    Regards

    Henrik
  6. Chuck
    Chuck avatar
    30 posts
    Member since:
    Sep 2010

    Posted 18 Apr 2012 Link to this post

    Viktor & Henrik,

    So it sounds like the main concern is when you are creating a relationship between two or more "new" objects.

    Good to know, and this is what I've been doing.

    However, in another scenario I may store a key value for a preexisting object in session state or view state and not persist the entire object between postbacks.  In this case it sounds like it is valid to create a new related object (parent or child - depending on the IsManaged property), and then set up the relationship using just the foreign key value I had previously stored.  I am not forced to make a round trip to the database to first create an instance of the original object in order to make sure the relation is successful.

    If this is not correct, please let me know.  I wanted to make sure there wouldn't be any unanticipated consequences.
  7. Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 20 Apr 2012 Link to this post

    Hello Chuck,

    If you already have the Id of the reference object, it is OK to set the foreign key Id property.

    One important consideration while using this approach is that if you try to access the navigation property later, the referenced object will be loaded from the database (with a query or from the OpenAccess cache if present).

    You may also have to take extra care to avoid/handle errors caused by incorrect/missing foreign key Ids.

    Kind regards,
    Viktor Zhivkov
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the OpenAccess ORM, subscribe to their blog feed now.
  8. Chuck
    Chuck avatar
    30 posts
    Member since:
    Sep 2010

    Posted 20 Apr 2012 Link to this post

    Thank you again!  I speak highly of your support & tools.
Back to Top
DevCraft banner