我目前有一个Repository / UnitOfWork模式。但是,有一种硬耦合我无法弄清楚如何摆脱它。
这是我的模式概述:
业务逻辑层
数据层(使用Ninject注入)
核心
这是我的通用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的要求。但是,这意味着重构变得烦人,因为它用魔术字符串填充代码。
答案 0 :(得分:1)
正如我发布的那样,我想我找出了问题所在。
Find()和FindAll()甚至不应该存在。我应该在IEmployeeRepository中编写更具体的方法,如FindEmployeeByName(字符串名称),然后像这样实现它:
EmployeeDTO FindEmployeeByName(string name)
{
return Mapper.Map<EmployeeDTO>(dbSet.Where(o=>o.name.Contains(name)).FirstOfDefault());
}
任何人都可以确认这是一种正确的方法吗?或者建议一些更好的东西?
修改强>
此外,如果我想保留Find(Expression ...)和FindAll(Expression ...)方法,我可以,但它们只是在数据层中,并由实现的方法使用,以避免重复的代码。但它们不应该用在控制器中,因为它们需要知道底层数据结构,而不是我的业务逻辑。也就是说,它们可以在BaseRepository&lt; TModel&gt; (我已经拥有,但没有提到让事情变得更简单)并使EmployeesRepository成为BaseRepository的扩展。这样,每个存储库都已经具有类似通用的方法,即模型识别。
不确定我是否正确解释了这一点。如果不清楚我会告诉我,我会尝试编辑它并使其更好。
答案 1 :(得分:0)
另一种方法是让您的数据层依赖于业务层,并将您的存储库“项目”实体放入业务对象(DTO)中。这样,您的BL位于底部,UI和数据依赖于它,但UI和数据不依赖于彼此。
这是Mark Seemann在他的“依赖注射”一书中提出的方法。