Id or reference to another root object?

Id or reference to another root object?

Old forum URL: forums.lhotka.net/forums/t/6341.aspx


alef posted on Thursday, February 05, 2009

Suppose we have two root objects.
Employee (FirstName, LastName,Country)
Country (Id,Description) ==> Id which is an autonumber

On the UI the user can add a new country while editing/adding an employee.
The employee has a reference to country object (not to the id).

Now when saving the objects, we first save the root object country. In case it is a new country the autonumber id is generated in the database and will be retreived in the object country.
Then we save the employee object.
As the employee has a reference to the country object everything will work when saving to the database. When the country object is inserted in the database, the id of country will be retrieved. Because the employee has an reference to the country object, we can add/modify the employee record in the database because we have access to the countryid via the reference to the object country.

If employee should not have a reference to country, but instead has a property countryid then I don't know how this could work? In the book of Lhotka I see that he is always using Id's. Why?

SonOfPirate replied on Thursday, February 05, 2009

It goes to the use case for the class.  In the cases described in the book and sample application, all that is needed is the identifier so that the object can be retrieved by id.  By maintaining an object reference, you make your object graph more rigid and deeper.  So, for instance, any time you serialize an Employee object, you also serialize the referenced Country object.

Your use case is not all that unusual, however, nor is it all that different.

I look at it like you have a master-child relationship in your UI with the Employee record displayed in the master view and the Country displayed in the child view.  You didn't mention if this was a WinForms, WPF, ASP.NET or other interface, so I'll run with ASP.NET (cuz I can explain it the quickest that way!).

I would setup my UI with two datasources: one for the Employee and one for the Country.  In the code-behind, my datasource knows to retrieve the Employee record based on the identifier passed to the page/form.  The second datasource is dependant upon the first and uses the Employee.CountryId value as the key to lookup the appropriate Country.  If the CountryId is Guid.Empty (for instance), your code would instantiate a new Country and bind the UI to that instance.

When saving, your code would save the Country object (thereby updating or inserting the record), update the Employee.CountryId property for new objects then save the Employee record.

Where the separation of objects becomes more intuitive is if we displayed a drop-down list of available countries for the user to select.  You would bind the drop-down control to a CountryList object with the key set to the Id value.  The selected item/value property of the drop-down list would be bound to the Employee.CountryId property.

I typically use the latter approach with a button adjacent to the drop-down or a special list item that the user can click to open a dialog for creating the new item (Country).  When the dialog is closed, the Country is saved and the list's datasource is refreshed, updating it with the new item thereby making it available for the user to select.

Hope that helps...

 

RockfordLhotka replied on Thursday, February 05, 2009

There's a specific coding difference between the containment and using relationships.

With containment, the parent maintains a direct, serializable and undoable reference to the child. This allows the .NET serialization mechanism, the CSLA undo mechanism and other features to work properly.

With a using relationship, one object may maintain a reference to another object, but that reference must not be serializable or undoable. Otherwise it is a containment relationship. Since it won't be serializable, your code must assume the value could be null, and so must have a way of recreating the reference. Normally you'd create the reference by calling the other object's factory method, and that typically requires an id value.

So no matter what, you need to maintain the id value so you can load/reload the other object. You can hold a reference, but the field holding that reference must be NonSerialized and NotUndoable.

Copyright (c) Marimer LLC