【问题标题】:Repository Pattern and Mapping between Business Objects and Data Access Objects存储库模式和业务对象和数据访问对象之间的映射
【发布时间】:2013-11-11 18:33:32
【问题描述】:

我在我的 .net MVC 项目中使用实体框架作为 ORM。我已经实现了存储库模式(通用)来获取/保存/更新/删除 DAO(数据访问对象)。我也有包含所有业务逻辑的业务对象。例如,我有一个名为 Student 的 DAO 和一个名为 Student 的 BO(业务对象)。 BO 包含逻辑,DAO 只是存储在 DB 中的数据。 现在我想知道学生存储库是否应该返回业务对象而不是 DAO? 我可以通过在从 Repository.Get() 返回之前将 DAO 转换为业务对象来使用 Automapper 来实现这一点。与所有其他方法相同。但这是一个好习惯吗?

更新

我有一个数据访问层项目和一个业务逻辑项目。实体框架在部分类中创建其实体(到数据访问项目中),因此我实际上可以使用其他部分类扩展实体,但问题是我在业务项目中引用了数据访问项目并且我无权访问数据访问项目中的逻辑代码。所以我必须将逻辑放在业务项目中,但由于不可能在两个项目上创建部分类,我必须采取另一种方式......或者你有一个好主意如何更好地构建和解决问题怎么办?

【问题讨论】:

    标签: c# .net entity-framework design-patterns business-logic


    【解决方案1】:

    是的,这完全是个好习惯。通常,您在域程序集中定义了存储库接口。这些接口由域服务使用,并在持久性组装中实现。 Entity Framework 允许您流畅地映射业务实体,而不会用属性污染它们或强制它们从某些特定的基类(POCO 实体)继承。这会让你的领域模型 Persistence Ignorant。

    【讨论】:

    • 感谢您的快速回答。我考虑过使用 AutoMapper 将业务对象映射到 dao,反之亦然。您正在写关于使用实体框架执行此操作的文章,对吗? - 你怎么能做到这一点?
    • @sjkm DAO 为您的应用程序带来了什么好处?如果您要重命名数据库中的表或列,那么您可以简单地更改映射。商业实体将保持不变。我没有看到任何好处。我看到的是两个需要创建和维护的新地方 - DAO 以及 DAO 和 BO 之间的映射。
    • 我有一个数据访问层项目和一个业务逻辑项目。实体框架在部分类中创建其实体,因此我实际上可以使用其他部分类扩展实体,但问题是我在我的业务项目中引用了 DAL 项目并且我无权访问 DAL 项目中的逻辑代码.所以我必须将逻辑放在业务项目中,但由于不可能在两个项目上创建部分类,我必须采取另一种方式......或者你有一个好主意如何更好地构建和解决问题大大地?我真的很感激!
    【解决方案2】:

    恕我直言,有几个目标(一些相互竞争):

    • 使业务逻辑可单独测试
    • 设计域对象以匹配您的域
    • 将数据访问与其他一切分离
    • 保持简单

    您可以在没有数据库的情况下测试您的业务逻辑吗?可能是的,无论这些类是 EF POCO 实体还是从 DAO 映射。

    您的域对象与您的域匹配吗?他们的名字选得好吗?它们是否始终处于有效状态? (这对于一堆公共读/写属性来说可能很困难。)领域驱动的设计考虑适用于此。 (我不是这方面的专家。)

    您能否在不更改数据访问层之外的任何内容的情况下,将 EF 换成 Dapper,将 SQL Server 换成 MongoDB,或者将当前数据访问换成 Web 服务调用 - 有信心吗?我的怀疑是否定的。通用存储库倾向于将 IQueryable 泄漏到其他层。并非所有东西都支持查询,而且提供者的实现也各不相同。单元测试通常使用 LINQ to Objects,它的行为与 LINQ to Entities 相同。此外,如果要提取 Web 服务合同,则必须查看所有类以查找所有查询。见IQueryable is Tight Coupling

    最后,您需要所有这些吗?如果您的应用程序的目的是 CRUD 数据访问,并且在简单验证之上没有业务逻辑,则可能不是。这些注意事项肯定适用于复杂的应用程序或网站。

    【讨论】:

    • 谢谢 TrueWill!我感谢您的帮助。我的应用程序(或将要)非常复杂。我认为更分离的代码会大大提高可维护性吗?我面临的另一个问题是我在上述 cmets 之一中描述的问题(对lazyberezovsky 的回答)。
    • 对于复杂的应用程序,我同意将 DAL 项目与域/业务逻辑项目分开。 DAO 也是一个合理的选择。
    • 很好的建议。我不得不从“通用存储库倾向于将 IQueryable 泄漏到其他层”这句话中推断出我正在寻找的答案,但这很好。
    • @JonKoeter 我愿意扩展这个答案;你会如何表达你正在寻找的东西?
    • @TrueWill 我会说“我应该在哪里将我的 DTO/数据对象/实体映射到我的域对象,它应该在业务层还是在存储库中?”。而且我想我在想所有有经验的程序员都认为这很明显,所以这就是它不明确的原因。但是当你说 IQueryables 泄漏到其他层是不好的时候,我很清楚。由于前面提到的原因(例如:将 EF 换成 Dapper 等),将您的东西映射到存储库中,保持解决方案的其余部分干净,仅使用仅包含必要信息的域对象。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 2018-01-08
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多