If the goal is to be able to swap out backend DB providers (EF, OleDB, ODBC, etc) then I'm wondering where the different DB CRUD changes? Currently I have an interface (IGenericContext) that has Add/Update/Delete/Select functions. I then make an ADOContext which implements this and inside these functions is where I do the SQL statements. For Add/Update/Delete this is fine, but select is interesting as I just take a string which is the sql. So in my repository where I have functions like, GetAllTasks() I just call that context.Select function with the sql statement.

However, if I then create an EFContext you wouldn't be able to call this Select function with the string sql. You'd do something that involved Linq which means my Repository needs the code change if I switch the context. Now that's better than the business layer needing a change, but it still seems like it would be nice to not have to change the repository as it's really the context that should handle those things and need to be changed and for Update/Add/Delete it does, but selecting seems more unique by context type.

How would you handle something like that? Imagine I created a text file context for that matter. It seems like it's fairly easy to hide the details of Add/Update/Delete but it's harder to hide the details of select from context from within the repository.


Your IGenericContextinterface won't change, but the underlying implementation will.

That's how this works. The Interface shields you from having to make changes to the consumers of the interface, if you conform to the interface when you write a new IGenericContext implementation. It does not, however, relieve you of having to write the new implementation.

Incidentally, your assertion that you can't use SQL with EF is not true. You can still get results from EF with raw SQL if you want to:

var students = context.Students.SqlQuery("SELECT * FROM dbo.Student").ToList();


var student = context.ExecuteQuery<Student>(
    "SELECT * FROM dbo.Student WHERE StudentID = {0}", 1234)
  • I have a repository and inside there is where I have a function like GetAllTasks. Inside that function I call the context Select function but I have to use a sql statement to do that. So now my repository is tied to sql which I wouldn't want. – user441521 Aug 5 '16 at 21:59
  • OK. So what's the problem? You don't want to use SQL, and would rather use Linq? – Robert Harvey Aug 5 '16 at 22:19
  • Those were just examples. If the physical storage of data is on something that doesn't support sql to get the data, and the repository has a get function how can the repository not be responsible for getting the data and instead pass that to the context because it's easy for the context to do the update, add, delete inside its own implementation by taking a POCO but getting data from the context within the repository doesn't seem like it can be abstracted out very well that I can see. – user441521 Aug 5 '16 at 22:30
  • IGenericContext is the abstraction. You still need an implementation, and that implementation is going to differ from data store to data store. – Robert Harvey Aug 5 '16 at 22:33
  • Yes I get that but that's just the context. If my repository has a function like GetAllTasks then how does it get that from the context because the context isn' my going to have that specific function on it. So how does it get it? What's the interface for getting it in a way that no code has to change in the repository itself if I change context. – user441521 Aug 5 '16 at 22:38

The Repository pattern is a layer on top of the Data Mapping pattern. From Fowler:

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects

Without a mapping layer in place, you should be using Table Data Gateway (also known as Data Access Object) and/or Transaction Script instead.

The goal of the repository pattern isn't to allow for swapping providers per se. That is a side effect. And by providers it happens to mean different O/RM mappers like EF, NHibernate, etc. The true benefit is that it gives you a seam that allows you to test your domain logic without hitting the database by using an "In-memory" repository/unit of work that you can build your unit tests around.

  • Yep I get that. I'm talking specifically in this case about the side effect and can the get part be abstracted to the specific implementation of a context because I can't see how it can given all the different ways to get data from all the different physical means to store data. It seems like that get part has to be specific to the type in the repository get type function – user441521 Aug 5 '16 at 22:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.