Должен ли идентификатор в бизнес-объекте быть только для чтения или нет? - PullRequest
8 голосов
/ 11 августа 2009

По моему мнению, поле идентификатора бизнес-объекта должно быть доступно только для чтения (общедоступное получение и закрытое множество), поскольку по определению идентификатор никогда не изменится (поскольку он однозначно идентифицирует запись в базе данных).

Это создает проблему, когда вы создаете новый объект (идентификатор еще не установлен), сохраняете его в базе данных с помощью хранимой процедуры, например, которая возвращает вновь созданный идентификатор, а затем, как сохранить его обратно в объекте, если идентификатор свойство только для чтения?

Пример:

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

EmployeeDAL.Save(employee);

Как метод Save (который фактически подключается к базе данных для сохранения нового сотрудника) обновляет свойство EmployeeId в объекте Employee, если это свойство доступно только для чтения (что должно быть, так как EmployeeId никогда не изменится после создания ).

Похоже, что идентификатор должен быть доступен для записи DAL и доступен только для чтения для остального мира. Как это реализовать, особенно если классы DAL и классы бизнес-объектов находятся в разных сборках?

Я не хочу создавать метод Save в классе Employee, поскольку этот класс не должен иметь ничего общего с базой данных.

Ответы [ 5 ]

2 голосов
/ 11 августа 2009

Другое возможное решение - объявить Сотрудника как: -

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

... при условии, что классы Employee и DAL находятся в одной сборке

Я не утверждаю, что мне это нравится, но я использовал это.

1 голос
/ 11 августа 2009

Как насчет того, чтобы только код вне DAL мог ссылаться на объект через интерфейс, который не предоставляет установщик для поля Id (и любых других неизменяемых полей):

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;}
}

DAL может установить его в соответствии с требованиями, но код потребления не может.

1 голос
/ 11 августа 2009

Вы можете заставить свой метод DAL просто возвращать обновленный объект:

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
    }
}

Кроме того, вы можете сгенерировать новый идентификатор в коде, создать экземпляр объекта с этим идентификатором, а затем попросить DAL сохранить его.

Если вы хотите, чтобы ваш объект был обновлен во время операции сохранения, вы должны сделать это свойство общедоступным.

Мне лично нравится создавать неизменных объектов, которые вы можете настроить только один раз, передав все значения в конструктор. При таком подходе вы просто создаете объект для сохранения, затем извлекаете его обратно вместе с назначенным идентификатором из базы данных и возвращаете его вызывающей стороне.

1 голос
/ 11 августа 2009

Вы можете установить свой установщик для разрешения идентификатора, только если он еще не был установлен ранее:

public class Employee
{
    private int? m_ID;

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

В качестве альтернативы, я думаю, что некоторые платформы поддерживают этот тип функциональности (например, я думаю, что NHibernate позволит вам иметь частный установщик для поля идентификатора).

0 голосов
/ 11 августа 2009

Как насчет:

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

Это также должно упростить ваш код сохранения.

...