Как мне справиться с созданием составных объектов с помощью DAL, свернутого вручную? - PullRequest
3 голосов
/ 06 октября 2011

По независящим от меня причинам я не могу использовать настоящий ORM, поэтому я вынужден создать пользовательский DAL, который располагается поверх необработанных данных и возвращает «доменные объекты» потребителю.Также по независящим от меня причинам я должен использовать хранимые процедуры для доступа к данным.

Я использую шаблоны Factory и Repository для доступа к данным или, по крайней мере, в базовыхТеория:

  1. Вызов SqlCommand и друзей скрыт классом Repository, который принимает необходимые параметры и возвращает объекты домена.
  2. Для создания объекта домена в репозитории имеется внутреннийссылка на фабрику своего типа (например, клиент, заказ и т. д.).У фабрики есть единственный метод, Create, который принимает DataRow в качестве входных данных и сопоставляет столбцы DataRow со свойствами объекта домена.

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

class Case
{
    public string CaseNumber { get; internal set; }
    public ICollection<Message> Messages { get; set; }
}

class Message
{
    public int MessageId { get; internal set; }
    public string Content { get; set; }
}

Проще говоря, Case has many Messages.Моя забота - лучший способ получить необработанные данные для дела, так как мне также нужен список связанных сообщений.Мне кажется, я могу либо:

  1. Запустить вторую хранимую процедуру в CaseRepository, когда я получаю Case, чтобы получить все принадлежащие ему сообщения - это не кажется хорошей идеей, потому чтоэто означает, что каждый раз, когда я просматриваю Case, я делаю два вызова базы данных вместо одного.
  2. Используйте одну хранимую процедуру, которая возвращает две таблицы (одна, содержащая одну строку с информацией для Case, одна, содержащая нольили более строк с сообщениями, которые ему принадлежат) и вызывают два фабричных метода, т.е. CaseFactory.Create (caseDataRow) и цикл, который вызывает MessageFactory.Create (messageDataRow).Это имеет больше смысла, так как Case - это совокупный корень (или притворяется единым в зависимости от случая), поэтому он должен знать, как создавать сообщения, зависающие от него.

Второй вариант выглядит лучшепроизводительность, но больше кода.Есть ли третий вариант, который я пропускаю, или # 2 - лучший способ обработки такого рода составных объектов, когда я не могу использовать истинный ORM (или даже что-то вроде Linq to SQL)

1 Ответ

3 голосов
/ 06 октября 2011

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

class Customer
{
    string name; // etc
    Address homeAddress;
    Order[] orders;
}

interface ICustomerTableGateway { ... }

interface IAddressTableGateway { ... }

interface IOrderTableGateway { ... }

class CustomerRepository
{
    Customer Get(int id)
    {
        customer = customerTableGateway.Get(id);
        customer.Address = addressTableGateway.Get(customer.id);
        customer.Orders = orderTableGateway.GetAll(customer.id);
    }
}

Если вы можете вернуть несколько таблиц из одного источника, это еще больше упрощает:)

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