使用Linq To SQL和DTO(数据传输对象)分离关注点

11

我最近开始一个新的Webforms项目,并决定将业务类与任何DBML引用分开。我的业务层类访问离散的数据层方法,返回DTO集合。因此,数据层可能会像以下这样投影DTO:

(from c in dataContext.Customers
where c.Active == true 
select new DTO.Customer
{
   CustomerID = c.CustomerID,
   Name = c.CustomerName,
   ...
}).ToList()

尽管构建DTO对象需要付出额外的工作,但这似乎是在业务层和数据层之间实现紧密绑定的更好方法,并且我可以在没有数据库的情况下测试业务层。

我的问题是,这是否是良好的实践?是否有一种生成DTO的方式(也许通过SQLMetal),以及随着项目进展可能会遇到什么其他问题。


我在这里发布了一些关于外部XML映射的链接:https://dev59.com/skfSa4cB1Zd3GeqPBvzF#1136039 - alexandrul
2个回答

5

我不知道这是否是最佳实践,但在不太久的过去时间里,我编写了类似的代码,因为我也觉得使用自己的类而不是应用程序中由LINQ设计器生成的类可以改善关注点分离。

您可能希望考虑仅从数据访问方法返回IQueryable<Customer>而不是IList<Customer>。由于IQueryable<T>继承自IEnumerable<T>,因此您的应用程序的其余部分应该能够很好地处理它。当您真正需要时,还可以将其转换为List。

这样做的好处是您可以轻松动态修改查询并将从SQL Server返回的数据量最小化。

例如,如果您的方法签名是IQueryable<Customer> GetCustomers(),则可以通过调用GetCustomers().Where(c => c.CustomerID == 101).Single()来获取单个客户。

在此示例中,仅从数据库返回一个记录,而我想象中您的代码当前将返回所有客户或者您需要编写单独的方法(因此非常重复)以满足您可能要按不同条件筛选的所有不同需求。


4
我建议相反的做法。除了在数据访问层以外,我永远不会返回一个 IQueryable 列表。如果你这么做,你的展示层可能会不知不觉地执行数据库查询,或者你可能会混合使用 Linq-to-objects 调用并得到一个 Linq-to-sql 错误。从 Linq-to-sql 返回 IQueryable 会导致架构很差并且泄漏问题,应该避免使用,除非是用于最简单的小型应用程序。 - mattmc3

2

在我看来,大多数情况下,在处理LINQ时不需要DTO对象。生成的LINQ类可以轻松测试。 LINQ使您能够使用相同的查询从不同的源查询数据。它使您能够针对对象列表而不是真正的数据库来测试查询。


同意。实质上,您的Linq-to-sql对象可以被视为DTO,并且甚至有一个T4模板可用于将您的L2S对象生成为可序列化的对象。 - mattmc3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接