По независящим от меня причинам я не могу использовать настоящий ORM, поэтому я вынужден создать пользовательский DAL, который располагается поверх необработанных данных и возвращает «доменные объекты» потребителю.Также по независящим от меня причинам я должен использовать хранимые процедуры для доступа к данным.
Я использую шаблоны Factory
и Repository
для доступа к данным или, по крайней мере, в базовыхТеория:
- Вызов SqlCommand и друзей скрыт классом Repository, который принимает необходимые параметры и возвращает объекты домена.
- Для создания объекта домена в репозитории имеется внутреннийссылка на фабрику своего типа (например, клиент, заказ и т. д.).У фабрики есть единственный метод,
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
.Моя забота - лучший способ получить необработанные данные для дела, так как мне также нужен список связанных сообщений.Мне кажется, я могу либо:
- Запустить вторую хранимую процедуру в CaseRepository, когда я получаю Case, чтобы получить все принадлежащие ему сообщения - это не кажется хорошей идеей, потому чтоэто означает, что каждый раз, когда я просматриваю Case, я делаю два вызова базы данных вместо одного.
- Используйте одну хранимую процедуру, которая возвращает две таблицы (одна, содержащая одну строку с информацией для Case, одна, содержащая нольили более строк с сообщениями, которые ему принадлежат) и вызывают два фабричных метода, т.е. CaseFactory.Create (caseDataRow) и цикл, который вызывает MessageFactory.Create (messageDataRow).Это имеет больше смысла, так как Case - это совокупный корень (или притворяется единым в зависимости от случая), поэтому он должен знать, как создавать сообщения, зависающие от него.
Второй вариант выглядит лучшепроизводительность, но больше кода.Есть ли третий вариант, который я пропускаю, или # 2 - лучший способ обработки такого рода составных объектов, когда я не могу использовать истинный ORM (или даже что-то вроде Linq to SQL)