Объектно-ориентированный дизайн: сохранение сложных объектов - PullRequest
1 голос
/ 12 ноября 2009

У меня сложная модель предметной области, построенная поверх унаследованной системы, для которой я построил большинство методов «get» - обычно просто путем передачи идентификаторов первичного ключа базы данных. Достаточно просто. Теперь мне любопытно, как подойти к задаче создания новых объектов в базе данных и сохранения существующих с новыми данными, и хочу убедиться, что я охватил все свои базы.

Основные доменные объекты, которые соответствуют сущностям в базе данных, насчитывают около 20-25 для всего проекта. Приблизительно 10 или около того должны быть сохранены (остальные только для поддержки данных и не нуждаются в обновлении пользователем). Сохраняемые объекты имеют сложные зависимости - у объекта A есть список объектов B, который, например, содержит объекты C, D и E, и все из них, возможно, потребуется сохранить, когда исходный объект A равен.

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

Другой альтернативой является предоставление методов «CreateNew» и «Save» для сервисных объектов, которые их обрабатывают, но список параметров для таких методов будет вопиющим.

Я думаю о том, что «CreateNew» и «Save» должны принимать что-то наподобие командного объекта, который они могут создавать и передавать, чтобы они точно знали, какие данные необходимы и что они не могут пытаться контролировать. Я прочитал о шаблоне команды , но мне не нужны никакие основные привилегии, которые он предоставляет.

Какие соображения я должен принять решение о подходе? Это C # 3.5, если это вообще учитывается.

Ответы [ 2 ]

1 голос
/ 12 ноября 2009

Вы должны исследовать популярные фреймворки объектно-реляционного отображения для .NET. Многие люди уже сталкивались с этой проблемой, и некоторые из самых умных поделились с нами плодами своего труда. У них есть множество функций, и самые популярные из них тщательно протестированы.

Кажется, что каждые несколько дней кто-то новый запрашивает рекомендации .NET ORM, поэтому существует множество тем о переполнении стека, которые могут помочь вам. Например:

(Если вы будете искать в «ORM» и «.NET», вы обнаружите еще много совпадений.)

При обычном использовании разработчик пользовательского интерфейса имеет дело только с высокоуровневыми родительскими объектами (так называемыми «совокупными корнями» на языке доменного проектирования). Они используют ORM в качестве репозитория , и это обеспечивает объединение всех операций в данном сохранении в разумные транзакции. (Вам по-прежнему необходимо применять валидность в соответствии с бизнес-правилами в объектах вашего домена.)

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

// Given an IRepository implemented by your ORM,
ICustomer customer = repository.Get(customerId);

// ... do stuff to customer and its child objects ...

repository.Save(customer);
1 голос
/ 12 ноября 2009

Вы можете заставить все ваши объекты предоставлять один и тот же метод, вызывать его AttemptSave, и вызов этого метода для родительского объекта приведет к тому, что он вызовет каскадно эти методы всех дочерних объектов.

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

Затем выставьте метод GetValidationErrors. Если AttemptSave вернул false, тогда разработчик пользовательского интерфейса должен вызвать этот метод для получения и отображения ошибок.

Кроме того, вы можете добавить метод проверки Validate, который будет предварительно проверять иерархию объектов. Вы можете вернуть ошибки проверки через GetValidationErrors. Затем будет выполнен вызов AttemptSave. В случае сбоя вы можете вернуть ошибки с помощью GetOperationErrors.

Что-то в философии SQL. Ваш запрос выполнен успешно или нет, вы всегда можете посмотреть на @@ ROWCOUNT, чтобы понять, выполнил ли запрос хотя бы часть работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...