简体   繁体   中英

Entity Framework vs repository pattern

I'm wondering about usefulness of repository pattern in project using Entity Framework. There are opposite claims about this - some say that EF is implementation of repository and Unit of Work pattern itself, so there is no need to wrap it in next abstraction layer, some argue that it has advantages like separation of DAL and BL and easier creation of unit tests. In my experience, I often come across the following approach (generally, not only in EF projects):

Repository (DAL) <-> Service (BL) <-> Controller

Repository + Service + Type = Model

Repository has methods responsible for data access only ie:

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);
  // ...
}

Often, there is used generic repository instead, which methods receive functions for filtering, sorting etc.

Service in turn uses repository and contains business logic ie:

public interface IUsersService
{
  // ...
  bool VerifyPassword(string login, string password);
  void ChangePassword(string login, string password);
  // ...
}

As I understand, service shouldn't have any DAL operations - this means that we shouldn't ie return IQueryable collections from repository, because then query will be executed outside repository and unit tests will not be fully reliable (differences between LINQ-to-Entities and LINQ-to-Objects).

I see a problem with queries efficiency here - we will often get more data from database than needed and then filter it in memory.

For example, let's consider bool VerifyPassword(string login, string password) method.

In this case we need to get whole User entity from database, which can have 50 properties for example, for password verification purpose only. We can, of course, create many methods in repository like :

string GetPasswordHash(string login) 

or

bool VerifyPassword(string login, string passwordHash) 
{
  return db.Users.Any(x => x.Login = login && x.Password = passwordHash);
} 

without need to get whole entity from database, but in my opinion this can be a "little" overhead.

We can also move VerifyPassword function from service to repository - then we should ask ourself a question whether two layers - repository and service are needed. But if we merge them, we will lose benefits of separating DAL and BL layers - unit tests would be integration tests in reality. So maybe it would be simplier (and better) to keep it all in controller and inject mocked DbContext or use something like Effort for unit tests?

I will be grateful for your answers how you see this and how you solve this problem in your projects.

UPDATE

I understand that repository pattern allows to easily change data source/provider to other like nHibernate, LINQ-to-SQL, plain ADO and so on.

But could you tell me how do you implement sorting and paging in your repository API? I mean what's the best way to pass sorting and paging specification to repository? I see that some passes function predicates for LINQ but this will tightly couple repository with LINQ - using it with plain ADO, stored procedures etc. would be problematic. Creating many methods like GetUsersOrderedByNameDesc() etc. is crazy in my opinion. So maybe create your own class for specification, forge and pass sorting/paging criterias, and process it in repository? If yes, can you provide me some example of implementation?

I will try to attempt your core question. Here are my two cents. Why repository vs entity framework. You will need to answer some of the questions I propose you ask when designing or picking which one:

  1. Is there a chance your project will have different repositories it will talk to? If yes, then repository pattern over entity framework makes sense.
  2. Having a repository pattern will also allow you to set up your test framework more easily where you can have your mockup db that the repository pattern (DAL) will use.
  3. You may also want to consider the changes to your data model can percolate back to changes in your business logic with the entity framework.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM