我想知道存储库模式在使用实体框架的项目中是否有用。在这方面有相反的说法--有人说EF是存储库和工作模式单元本身的实现,因此没有必要将它封装在下一个抽象层,一些人认为它具有DAL和BL分离以及更容易创建单元测试的优点。根据我的经验,我经常会遇到以下方法(一般情况下,不仅在EF项目中):
Repository (DAL) <-> Service (BL) <-> Controller
Repository + Service + Type = Model存储库只有负责数据访问的方法,即:
public interface IUsersRepository
{
IEnumerable<User> GetAll();
User Get(int id);
User GetByLogin(string login);
void Update(User item);
void Delete(int id);
void Delete(User item);
// ...
}通常,使用泛型存储库,哪些方法接收过滤、排序等功能。
服务反过来使用存储库并包含业务逻辑,即:
public interface IUsersService
{
// ...
bool VerifyPassword(string login, string password);
void ChangePassword(string login, string password);
// ...
}据我所知,服务不应该有任何DAL操作--这意味着我们不应该从存储库返回IQueryable集合,因为查询将在存储库之外执行,单元测试将不完全可靠(和LINQ之间的差异)。
我在这里看到了查询效率的一个问题--我们通常会从数据库中获得比需要的更多的数据,然后在内存中过滤它。
例如,让我们考虑bool VerifyPassword(字符串登录,字符串密码)方法。
在这种情况下,我们需要从数据库中获取整个用户实体,该数据库可以具有50个属性,例如,仅用于密码验证。当然,我们可以在存储库中创建许多方法,如:
string GetPasswordHash(string login) 或
bool VerifyPassword(string login, string passwordHash)
{
return db.Users.Any(x => x.Login = login && x.Password = passwordHash);
} 不需要从数据库中获取整个实体,但在我看来,这可能是一个“小”开销。
我们还可以将VerifyPassword函数从服务转移到存储库--然后我们应该问自己是否需要两个层--存储库和服务。但是如果我们合并它们,我们将失去分离DAL和BL层的好处--单元测试实际上就是集成测试。因此,也许将其保存在控制器中并注入模拟的DbContext或使用类似于单元测试之类的方法会更简单(也更好)?
我将感谢您的回答,您如何看待这一点,以及如何解决这个问题在您的项目。
更新
我理解存储库模式允许轻松地将数据源/提供程序更改为其他类型,如nHibernate、LINQ、普通ADO等等。
但是,您能告诉我如何在存储库API中实现排序和分页吗?我的意思是,将排序和分页规范传递给存储库的最佳方法是什么?我看到一些用于LINQ的传递函数谓词,但这将使存储库与LINQ紧密耦合--使用它与普通ADO、存储过程等一起使用将有问题。在我看来,创建许多方法(如GetUsersOrderedByNameDesc()等)是很疯狂的。那么,也许可以为规范创建自己的类,伪造和传递排序/分页准则,并在存储库中处理它?如果是,你能给我提供一些实现的例子吗?
发布于 2014-06-15 18:53:07
我试着回答你的核心问题。这是我的两分钱。为什么存储库与实体框架。您需要回答我建议您在设计或选择哪一个问题时提出的一些问题:
https://stackoverflow.com/questions/24231791
复制相似问题