我应该如何处理用手工生成的DAL创建复合实体?
本文关键字:DAL 创建 实体 复合 何处理 处理 我应该 | 更新日期: 2023-09-27 18:10:39
由于我无法控制的原因,我不能使用真正的ORM,所以我被迫创建一个自定义DAL,它位于原始数据之上,并将"域对象"返回给消费者。另外,由于我无法控制的原因,我必须使用存储过程进行数据访问。
我正在使用Factory
和Repository
模式进行数据访问,或者至少在基本理论中:
- 对SqlCommand和friends的调用由Repository类隐藏,该类根据需要接受参数并返回域对象。
- 为了创建域对象,存储库有一个对自己类型的工厂的内部引用(例如Customer、Order等)。工厂有一个方法,
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
。我关心的是检索Case原始数据的最佳方式,因为我还需要一个关联消息列表。在我看来,我可以:
- 当我检索一个Case以获得属于它的所有消息时,在CaseRepository中运行第二个存储过程—这似乎不是一个好主意,因为这意味着每次我查找一个Case时,我都要进行两次数据库调用而不是一次。
- 使用一个存储过程返回两个表(一个包含单行信息的情况下,一个包含零或多行消息属于它),并调用两个工厂方法,即CaseFactory.Create(caseDataRow)和一个循环调用MessageFactory.Create(messageDataRow)。这更有意义,因为Case是聚合根(或者根据情况假装是一个根),所以应该知道如何创建挂起它的消息。
第二个选项似乎性能更好,但代码更多。当我不能使用真正的ORM(甚至像Linq to SQL)
就目前而言,您的存储库更像是表网关(甚至通过进程)。您将需要一个新的存储库层,它可以访问一个或多个表网关,并且能够根据从许多表返回的数据组装复合域实体。
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);
}
}
如果您可以从单个进程返回多个表,那么将进一步简化事情:)