2011-10-06 17 views
3

由于我无法控制的原因,我无法使用真正的ORM,因此我不得不创建一个位于原始数据上的自定义DAL,并向消费者返回“域对象”。此外,由于我无法控制的原因,我必须使用存储过程进行数据访问。我应该如何处理用手卷DAL创建复合实体?

我的基本理论,利用该FactoryRepository模式进行数据访问的,或至少:

  1. 到的SqlCommand和朋友的调用由库类,它的参数根据需要和收益隐藏域对象。
  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第二个存储过程时,我检索一个案例拿到属于它的所有信息 - 这似乎不是一个好主意,因为这意味着每当我查找一个案例时,我正在做两个数据库调用而不是一个。
  2. 使用一个存储过程返回两个表(其中一个包含带有Case的信息的单个行,一个包含具有属于它的消息的零个或多个行)并调用两个工厂方法,即CaseFactory.Create(caseDataRow)和a循环调用MessageFactory.Create(messageDataRow)。这样做更有意义,因为Case是聚合根(或者假装是根据具体情况而定),所以应该知道如何创建挂在它上面的消息。

第二个选择似乎更好的性能,但更多的代码。有没有第三种选择,我忽略或#2是处理这种复合对象的最佳方式,当我不能使用真正的ORM(甚至像Linq到SQL)

回答

2

因为它,你的存储库更像桌面网关(甚至通过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); 
    } 
} 

如果能够从单一的存储过程比返回多个表进一步简化事情:)

+0

嗯,我从来没有完全得到信息库和TDG之间的区别;我见过的每个演示使用的存储库基本上都是我在这里使用的,你说的更像是一个网关。 –

+0

我使用的NHibernate不支持sprocs返回多个结果集,所以我尝试将对象层次结构压扁成单行。这适用于1-1关系,1-many需要额外的电话。如果您的自定义DAL可以处理返回多个结果集的sprocs,那么这是一个很好的perf win :) – MattDavey

+1

teminology有点模糊 - “存储库”非常模糊。就我个人而言,我使用表格网关来返回DTO和储存库来协调表格网关并将DTO组装到领域模型中。 – MattDavey