0

我目前有一个 Repository/UnitOfWork 模式。但是,我无法弄清楚如何摆脱这种硬耦合。


这是我的模式的概述:

业务逻辑层

  • 存储库
    • 用作类型约束
  • IRepository< TModel, TDTO >
    • 实现 IRepository
    • 一般 CRUD 方法
  • IEmployeeRepository<TModel>
    • 实现 IRepository< TModel, EmployeeDTO >
    • 一些员工特定的方法
  • 工作单位
    • 存储库的吸气剂
    • 保存方法
  • IEntityWithId
    • 强制(和公开)DTO 和 EF POCO 具有称为 ID 的 Int32 字段的接口
    • 用作类型约束
  • EmployeeDTO(在实现的 EmployeeRepository 中使用 AutoMapper 映射)
    • 核心项目和(即将到来的)测试项目中使用的 DTO 实体

数据层(用 Ninject 注入)

  • 工作单位
    • 基于Entity Framework的IUnitOfWork实现
  • 员工资料库
    • IEmployeeRepository<TModel>的实现
  • 员工
    • 英孚波科

  • 员工控制器
    • 参数化构造器EmployeesController(IUnitOfWork unitOfWork)
    • IUnitOfWork 被注入一个 Ninject 模块作为一个 UnitOfWork(来自数据层)

这些是我的通用 IRepository 接口中的问题方法。

TDTO Find(Expression<Func<TModel, bool>> filter);

IEnumerable<TDTO> FindAll(Expression<Func<TModel, bool>> filter);

如您所见,其中有 TModel,用于构建表达式以过滤结果。我可以做一些事情,比如在 DTO 上使用表达式,但这需要映射到 DTO 的员工的完整列表(也就是它不会生成 SQL 过滤器,但它会过滤 SELECT * FROM Employee 结果列表)。所以这不是一个好的选择。

另一种更可行但不是最佳的解决方案是使用动态 LINQ。这样,我可以在 Find / FindAll 方法中传递一个简单的字符串并摆脱 TModel 要求。然而,这意味着重构变得烦人,因为它用魔术字符串填充代码。

4

2 回答 2

1

就像我发布这个一样,我想我知道我的问题出在哪里。

Find() 和 FindAll() 甚至不应该存在。我应该在 IEmployeeRepository 中编写更具体的方法,例如 FindEmployeeByName(string name),然后像这样实现它:

EmployeeDTO FindEmployeeByName(string name)
{
    return Mapper.Map<EmployeeDTO>(dbSet.Where(o=>o.name.Contains(name)).FirstOfDefault());
}

任何人都可以确认这是一种正确的方法吗?或者提出更好的建议?

编辑

另外,如果我想保留 Find(Expression...) 和 FindAll(Expression...) 方法,我可以,但它们只是在数据层中,并由已实现的方法使用,以避免重复代码。但它们不应该在控制器中使用,因为它们需要了解我的业务逻辑之外的底层数据结构。也就是说,它们可以在 BaseRepository<TModel> 中实现(我已经有但没有提及以使事情更简单)并使EmployeesRepository 成为BaseRepository 的扩展。这样,每个存储库都已经拥有那些模型感知的类泛型方法。

不确定我是否解释得当。如果不清楚,请告诉我,我会尝试对其进行编辑并使其变得更好。

于 2012-10-29T17:11:21.683 回答
0

另一种方法是让您的数据层依赖于业务层,并将您的存储库“项目”实体放入您的业务对象 (DTO)。这样你的 BL 在底部,UI 和 Data 依赖它,但 UI 和 Data 不相互依赖。

这是 Mark Seemann 在他的依赖注入一书中所支持的方法。

于 2012-10-29T17:16:28.030 回答