我应该如何处理用手工生成的DAL创建复合实体?

本文关键字:DAL 创建 实体 复合 何处理 处理 我应该 | 更新日期: 2023-09-27 18:10:39

由于我无法控制的原因,我不能使用真正的ORM,所以我被迫创建一个自定义DAL,它位于原始数据之上,并将"域对象"返回给消费者。另外,由于我无法控制的原因,我必须使用存储过程进行数据访问。

我正在使用FactoryRepository模式进行数据访问,或者至少在基本理论中:

  1. 对SqlCommand和friends的调用由Repository类隐藏,该类根据需要接受参数并返回域对象。
  2. 为了创建域对象,存储库有一个对自己类型的工厂的内部引用(例如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原始数据的最佳方式,因为我还需要一个关联消息列表。在我看来,我可以:

  1. 当我检索一个Case以获得属于它的所有消息时,在CaseRepository中运行第二个存储过程—这似乎不是一个好主意,因为这意味着每次我查找一个Case时,我都要进行两次数据库调用而不是一次。
  2. 使用一个存储过程返回两个表(一个包含单行信息的情况下,一个包含零或多行消息属于它),并调用两个工厂方法,即CaseFactory.Create(caseDataRow)和一个循环调用MessageFactory.Create(messageDataRow)。这更有意义,因为Case是聚合根(或者根据情况假装是一个根),所以应该知道如何创建挂起它的消息。

第二个选项似乎性能更好,但代码更多。当我不能使用真正的ORM(甚至像Linq to SQL)

我应该如何处理用手工生成的DAL创建复合实体?

时,是否有第三个选项我忽略了,或者#2是处理这种复合对象的最佳方法?

就目前而言,您的存储库更像是表网关(甚至通过进程)。您将需要一个新的存储库层,它可以访问一个或多个表网关,并且能够根据从许多表返回的数据组装复合域实体。

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

如果您可以从单个进程返回多个表,那么将进一步简化事情:)