Question

In my mind the ID field of a business object should be read-only (public get and private set) as by definition the ID will never change (as it uniquely identifies a record in the database).

This creates a problem when you create a new object (ID not set yet), save it in the database through a stored procedure for example which returns the newly created ID then how do you store it back in the object if the ID property is read-only?

Example:

Employee employee = new Employee();  
employee.FirstName="John";  
employee.LastName="Smith";  

EmployeeDAL.Save(employee);

How does the Save method (which actually connects to the database to save the new employee) update the EmployeeId property in the Employee object if this property is read-only (which should be as the EmployeeId will never ever change once it's created).

It looks like the Id should be writable by the DAL and read-only for the rest of the world. How do you implement this especially if the DAL classes and the Business object ones are in different assemblies?

I don't want to create a Save method in the Employee class as this class should have nothing to do with the database.

Was it helpful?

Solution

Another possible solution is to declare Employee as :-

public class Employee
{
    public int Id { get; internal set; }
}

... provided that the Employee and DAL classes are in the same assembly

I don't claim to like it but I have used it.

OTHER TIPS

You can make your DAL method just return an updated object:

public class EmployeeDAL
{
    Employee EmployeeDAL.Save (Employee employee)
    {
        // Save employee
        // Get the newly generated ID
        // Recreate the object with the new ID and return it
    }
}

Alternatively, you can generate a new ID in code, instantiate an object with this ID then ask your DAL to save it.

If you wish that your object was updated during Save operation you will have to make this property public.

I personally like to create immutable objects, those you can only setup once by passing all the values into constructor. With this approach you would just create an object to be saved, then retrieve it back along with the assigned ID from the database and return it to the caller.

You could make your setter for the ID allow set only if it has not already been set before:

public class Employee
{
    private int? m_ID;

    public int? ID
    {
        get { return m_ID; }
        set
        {
            if (m_ID.HasValue())
                throw ...
            m_ID = value;
        }
    }
}

Alternatively, I think some frameworks support this type of functionality (for example, I think NHibernate will allow you to have a private setter on an ID field).

How about only allowing code outside the DAL to refer to the object through an interface which doesn't supply a setter for the Id field (and any other immutable fields):

public interface IEmployee
{
    Int32 Id {get;}
    String Name {get;set;}
    // ... and so on ...
}

public class Employee: IEmployee
{
    Int32 Id {get;set;}
    String Name {get;set;}
}

The DAL can set it as required, but the consuming code can't.

How about:

Employee employee = new Employee(EmployeeDAL.GetNextID());

This should also make your save code simpler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top