我想知道使用Entity Framework在项目中存储库模式的有用性。对此有相反的说法 - 有人说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之间的差异) -to-Entities和LINQ-to-Objects)。
我发现这里的查询效率存在问题 - 我们经常从数据库中获取比需要更多的数据,然后在内存中过滤它。
例如,让我们考虑 bool VerifyPassword(字符串登录,字符串密码)方法。
在这种情况下,我们需要从数据库中获取整个User实体,例如,可以有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或使用像Effort这样的单元测试会更简单(也更好)?
我将非常感谢您的答案,您如何看待这个以及如何在项目中解决这个问题。
更新
据我所知,存储库模式允许轻松地将数据源/提供程序更改为其他类似nHibernate,LINQ-to-SQL,普通ADO等。
但是,您能告诉我如何在存储库API中实现排序和分页?我的意思是将排序和分页规范传递给存储库的最佳方法是什么?我看到一些传递函数谓词用于LINQ,但这会将存储库与LINQ紧密耦合 - 将它与普通的ADO,存储过程等一起使用会有问题。在我看来,创建GetUsersOrderedByNameDesc()等许多方法都很疯狂。那么可能为规范,伪造和传递排序/分页标准创建自己的类,并在存储库中处理它?如果是的话,你能给我一些实施的例子吗?
答案 0 :(得分:0)
我会尝试尝试你的核心问题。这是我的两分钱。 为什么存储库与实体框架。在设计或挑选哪一个问题时,您需要回答我建议您提出的一些问题: