You might feel this is homework, for that I am sorry. I have searched but couldn't find a proper answer.
So my question is:
I have several classes and each class has a method to save. So I created a separate class for database handling.
namespace HospitalMgt.Data
{
public static class DBConnection
{
public static string constr = "Data Source=ABD;Initial Catalog=HospitalMgt;User Id=sa;Password=123";
public static SqlConnection con;
// public static SqlCommand com;
public static SqlConnection OpenConnection()
{
con= new SqlConnection(constr);
con.Open();
return con;
}
}
}
However, I don't think it's suitable to implement all the classes with a DBConnection class.
My question :
What design pattern is suited to overcome this problem?
Is it good practise to create DBConnection as class? (Or should it be an Interface)
I found a few articles about DA layers using the Factory method, but according to my knowledge, that pattern does not suit my situation.
Normally, if I can't use any existing framework, I use both the Repository and Active patterns.
For simplicity, you could use only the Repository pattern. I normally define it like this:
public interface IEntity<T> { }
// Define a generic repository interface
public interface IRepository<TKey, TEntity>
where TEntity : IEntity<TKey>
{
void Add(TEntity entity);
void AddRange(IEnumerable<TEntity> entities);
IEntity<TKey> Get(TKey key);
IEnumerable<TEntity> GetRange(IEnumerable<TKey> keys);
IEnumerable<TEntity> GetAll();
// ..., Update, Delete methods
}
// Create an abstract class that will encapsulate the generic code
public abstract class Repository<TKey, TEntity> : IRepository<TKey, TEntity>
where TEntity : IEntity<TKey>
{
protected Repository(/*parameter you may need to implement the generic methods, like a ConnectionFactory, table name, entity type for casts, etc */) { }
public override void Insert(IEntity<TKey> entity)
{
// do the insert, treat exceptions accordingly and encapsulate them in your own and more concise Exceptions, etc
}
// ...
}
// Create the entities classes, one for each table, that will represent a row of that table
public class Car : IEntity<string> {/* Properties */}
// Create a specific repository for each table
// If the table have a composed key, just create a class representing it
public class CarRepository : Repository<string, Car>
{
public CarRepository() {/* pass the base parameters */}
// offer here your specific operations to this table entity
public IEnumerable<Car> GetByOwner(PersonKey ownerKey)
{
// do stuff
}
}
Obviously, when doing your own implementations, you must take into account thread safety making good using of transactions, specially across diferent entity repositories.
// simple example
ITransaction t = TransactionFactory.GetNewTransaction();
t.begin();
try{
// create person entity
personRepository.Add(person, t);
// create cars assigned to person
carRepository.AddRange(cars, t);
t.commit();
}catch(Exception){
t.rollback();
}
Just be sure that you really want to create your own DAL since it can end beeing extremelly complex, specially trying to develop the most generic solution.
First of all, I would like to recommend you the article Design Patterns for Data Persistence by Jeremy Miller.
There are some data access layer patterns:
Active record pattern (wiki, Detailed info).
Repository pattern (Detailed info).
I suggest using an ORM, Entity Framework or NHibernate will do nicely. Then you do not have to worry about a db context or create SQL statements.
Its too old but just came around this question and could not resist to post my thoughts.
I found Repository with UnitOfWork with some descent ORM is good approach. This minimizes most of the issues.
The UoW mentioned in above link can be injected in Repository. That increases the flexibility of usage. Also, all DB Communication code is centralized at one place. The example is not complete but a startup point.
Repository pattern mentioned in above link is actually a generic base class. You can create new class for each of your concrete Repository that derives from it.
Generic repository is considered an anti pattern; there are lot many articles on internet that explains it.
Why generic repository is anti-pattern?
A repository is a part of the domain being modeled, and that domain is not generic.
Not every entity can be deleted.
Not every entity can be added
Not every entity has a repository.
Queries vary wildly; the repository API becomes as unique as the entity itself.
For GetById(), identifier types may be different.
Updating specific fields (DML) not possible.
Generic query mechanism is the responsibility of an ORM.
Most of the ORMs expose an implementation that closely resemble with Generic Repository.
Repositories should be implementing the SPECIFIC queries for entities by using the generic query mechanism exposed by ORM.
Working with composite keys is not possible.
It leaks DAL logic in Services anyway.
Predicate criteria if you accept as parameter needs to be provided from Service layer. If this is ORM specific class, it leaks ORM into Services.
I suggest you read these (1, 2, 3, 4, 5) articles explaining why generic repository is an anit-pattern.
Solution:
Write an abstract Generic Repository that is wrapped by a concrete repository. That way you can control the public interface but still have the advantage of code-reuse that comes from generic repository.
Use a Generic Repository but do use composition instead of inheritance and do not expose it to the domain as a contract.
In any case, do not expose Generic Repository to calling code. Also, do not expose IQueryable from concrete repositories.
I suggest you to use a RepositoryBase for all this common operations. If you decide to use an ORM for data access it's good to think in a implementation of repositories based on a Generic Type repository.
Here is a good article about it:
http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/
Related
So I had a discussion with a coworker on implementing contract from a Base class to an interface.
We have the following structure with DDD, Api -> Application -> Domain -> Infrastructure.
In the infrastructure we use EF Core.
The following code example
Application
public interface IOrderRepository
{
IUnitOfWork UnitOfWork { get; }
Task AddOrderAsync(Order order);
}
Infrasctucture
public class OrderRepository : BaseRepository<Order, DbContext>, IOrderRepository
{
public OrderRepository(DbContext ctx) : base(ctx) { }
public async Task AddOrderAsync(Order order)
{
try
{
await AddAsync(order);
}
catch (Exception ex)
{
Log.Error($"Exception: {ex}");
throw ex;
}
}
/*
*
* Some other db methods
*
*/
}
public abstract class BaseRepository<T, U> where T : class where U : BaseDbContext, IUnitOfWork
{
protected readonly U _context;
public IUnitOfWork UnitOfWork
{
get
{
return _context;
}
}
public BaseRepository(U context)
{
_context = context;
}
protected virtual async Task AddAsync(T entity)
{
await _context.Set<T>().AddAsync(entity);
}
}
So I am arguing for, instead of implementing AddNAMEAsync methods in every repository to make AddAsync public virtual in the base class, and in corresponding interfaces and making use of the base class implementation. This way we also still have the possibility to orderride AddAsync if needed and also minimize unneccesary "duplicate code" in repositories.
My coworker on the other hand thinks that this will make the name too generic and when calling the repository you will not know which entity you are adding to the context by just reading the code. And aslo arguing on that we should not expose base class methods in interfaces, but that it instead should only be Parent -> Child exposure.
We are using SOLID principles and each handler only handles one entity/domain aggregate, we also have very clear naming on our variables/objects so you can easily see what you are adding to the context in the repository name as well as in the domain model
You can use AddAsync(T entity) method in BaseRepository, this will be provided reusable code for all your entities but this is already been implemented by Entity Framework Core. Do you really need to implement this structure again?
EF Core already provides the DbSet as base repository and DbSet<Order> as your order repository. Also provides DbContext as a unit of work implementation.
You don't need to create your generic base repository, repository, and unit of work classes if you don't use any other ORM tool or approach of persistence with EF Core. EF Core already provides these patterns as encapsulated.
What will encapsulating the classes and methods provided by EF Core solve in this way?
What are the differences between EF Core's DbSet and your BaseRepository?
See this sample project
In terms of naming you can, from my point-of-view, safely use "AddAsync()". The more important thing is that the client working with the repository uses a type of IOrderRepository. In this case, when looking at AddOrderAsync() the Order part could be seen as redundant in terms of naming because, first, you are calling it on a type that already indicates that everything is about orders, and second, you are passing an object of type Order which again indicates what you are going to add.
What you could still do is to make explicit that the generic methods are also part of an generic interface (e.g. IRepository) which IOrderRepository could extend. If you want to derive your infrastructure OrderRepository from a base class or if you want to pass it in some other object in terms of favouring composition over inheritance (e.g. a DbContext) is an implementation detail.
You can see an illustration of what I'm referring to here in the microservices reference application of Microsoft (eshopOnContainers).
I think you are right about implementing the AddAsync() method in a base class and inherit other classes from it. Because, when you want to use AddAsync() you will first inject the related class and then use it. (It will provide reusable code-base for you)
public class MyClass
{
private readonly OrderService _orderService;
//..
await _orderService.AddAsync(...);
}
There is no problem in terms of naming in this type of use, because the relevant service and what it will do are very clear.
Btw, CreateAsync or InsertAsync could be a better naming in my opinion to demonstrate database operation.
I am understanding repository pattern in c#. I am confused when i study about generic repository pattern. There is lot of repetition in it. i have some question about this pattern.
I am using Entity Framework code first approach and i have two model classes
Student
Teachers
How many generic interface i will use for example if i have one
generic interface
public interface IRepository<TEntity>
{
IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null);
TEntity FindOne(Expression<Func<TEntity, bool>> where = null);
}
So this interface can be use in both model classes.
if Student class have more methods where i can define these methods? for example
public class StudentRepo<TEntity> : IRepository<TEntity> where TEntity : class
{
public virtual IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null)
{
return null != where ? Context.Set<TEntity>().Where(where) : Context.Set<TEntity>();
}
public virtual TEntity FindOne(Expression<Func<TEntity, bool>> where = null)
{
return FindAll(where).FirstOrDefault();
}
public void update()
{
}
public int FindId()
{
}
}
So i have added two new methods update() and FindId() in StudentRepo where can I define these methods?
If I want to add these two methods in IRepository then I have to call these methods for Teacher class. what will be benefit of it?
Is this better approach if i create separate interface for both classes? like IStudent and ITeacher so i can define those methods which i want to use and unnecessary methods will not be in use.
Kindly guide me i am so confused.
You can have one implementation for the IRepository that you have, something like:
public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
public virtual IEnumerable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null)
{
// implementation ...
}
public virtual TEntity FindOne(Expression<Func<TEntity, bool>> where = null)
{
// implementation
}
public void Update(TEntity entity)
{
// update your entity ...
}
// etc...
}
Then have your own repository inheriting from it:
public class StudentRepository : GenericRepository<Student>
{
// here you get all the goodies + you can add your own stuff
}
And:
public class TeacherRepository : GenericRepository<Teacher>
{
// here you get the same goodies, you don't need to re-implement them
}
This way you don't have to re-implement all the methods defined in the generic repository, you can however add your own more complex methods.
Generic repositories are worthless. They just do the same thing as entity framework and most of the implementations out there expose IQueryable<T>.
So why is that so bad?
The repository pattern is used to create an abstraction between the data source and your code. That abstraction is created to reduce complexity and to reduce coupling between those tiers.
A generic repository might seem to be a good choice at first, but as every entity (root aggregate) have their own unique features you will always have to write custom queries to fetch them.
To solve that, most generic implementations expose IQueryable<T>. That is a bad thing since there is no 100% complete Linq to Sql provider (a set of classes which translates the LINQ statement to a SQL statement). Every provider has to resort to custom commands to support eager/lazy loading, support for IN sql clause etc.
You always have to be aware of those customizations every time you use the repository through IQueryable<T>.
Hence you still have to know about how Entity Framework works. You could therefore use EF directly instead of using a generic repository.
If you truly want to use the repository pattern, please design your code first with all your classes. And THEN create the database. That is, fit the DB after your code and not vice versa. And make sure that your repository is 100% complete abstraction (google for instance persistance ignorance)
I think that the Generic Repository idea is trying to generalize too much, seperate interfaces are better in my opinion as they provide a more meaningful contract, this blog explains it very good, and offers to use the generic repository "behind the scenes".
Okay, I need some help here.
This is the same old "can't use an interface to enforce constructors/static methods" problem.
WHAT IS THE PROPER OO DESIGN THEN??
I have a set of data entities (Entity Framework stuff) for which I wrote partial class methods to convert to/from XML (XElement objects).
I have an instance method to "save" XML:
// Convert entity to XML
public XElement ToXml() {}
...and I have a constructor to "read" XML:
// Create entity from XML constructor.
public MyEntity(XElement) {}
Alternatively, I could use a static factory method to "read" XML:
public static MyEntity ParseXml(XElement) {}
The dilemma:
I could create an interface that mandates the "save" ToXml() method, but what good is that if it only addresses half the problem? An interface can't enforce either of the "load" methods.
I could rely on my own good intent to create these methods without any sort of contract.
I could create a static class filled with redundant methods like XmlToEntity1() and XmlToEntity2(), etc... (Now I've described a good 'generics' problem.) However, the specific conversion code (which is specific to each entity) would create separate methods or switch/case for each and seems to belong inside the entity classes, not in some other class, no?
If an experienced C# coder can show a good design for this common problem I think I would learn a lot from it.
Happy 4th of July!
Possible Solution 1
A single XmlSerializer class with two static generic methods:
public static T Deserialize<T>(XElement xml) {}
public static XElement Serialize<T>(T entity) {}
Pro: Only one class (no interface needed)
Pro: Separates serialization responsibility from entity classes.
Con: Would still require separate methods or switch/case blocks for each entity type supported.
Con: ? Not extensible -- have to modify this class each time an entity changed or added/deleted.
Possible lessons learned?
The "can't use interface for constructors and static methods" problem might be a symptom of:
Violating the SRP (Single Responsibility Principal).
Violating the SoC (Separation of Concern) principal.
What about using a simple instance method for loading from XML as well? Your interface would then be something like:
public interface XmlSerializableEntity
{
XElement Serialize(); // or ToXml() if you prefer..
void Deserialize(XElement e); // or Load() or something like that..
}
Or you could use a generic solution:
public interface Serializable<T>
{
T Serialize();
void Deserialize(T e);
}
The downside is that you have to initialize the entity object before you load it, which might mean you'll have an object in an invalid state. But I do believe this is a common pattern.
It would be a good design to have the storage/retrieval separate from the entity anyway. In OO terms this can be referred to as the Single Responsibility Principle. Your entity exists for some purpose (probably related to your domain). The storage of that entity is a separate responsibility that could change independent of the domain. (e.g. you could retrive it from a database, a web service or the file system).
Static methods are not the only way to do this of course. You could create an interface at the save/retrive level and implement that interface for each of the entities. Then you could easily use those in a generic way without worrying a lot about the types.
Adding some example code:
interface EntityGateway<TEntity> {
TEntity Load(String id);
void Save(TEntity entity);
}
public class XEntityGateway implements EntityGateway<XEntity> {
XEntity Load(String id) { ... implementation details }
void Save(XEntity entity) { ... implementation details }
}
XEntityGateway gw = new XEntityGateway();
XEntity entity = gw.Load("SOMEID");
// modify entity
gw.Save(entity);
What is a IRepository? Why is it used, brief and simple examples won't hurt.
MVC promotes separation of concerns, but that doesn't stop at the M V C level.
Data Access is a concern in itself. It should be done in the M bit of MVC, ie the model. How you structure your model is up to you, but people usually follow tried and tested patterns (why reinvent the wheel?). The Repository Pattern is the current standard. Don't expect a simple formula, however, because the variations are as many as there are developers, almost.
IRepository is just an interface that you create (it is not part of MVC or ASP.NET or .NET). It allows you to "decouple" your repositories from real implementations. Decoupling is good because it means your code...:
Your code is much more reusable. This is just plain good.
Your code can use Inversion of Control (or Dependency Injection). This is good to keep your concerns well separated. It is especially good because this allows Unit Testing...
Your code can be Unit Tested. This is especially good in large projects with complex algorithms. It is good everywhere because it increases your understanding of the technologies you are working with and the domains you are trying to model in software.
Your code becomes built around best practices, following a common pattern. This is good because it makes maintenance much easier.
So, having sold you decoupling, the answer to your question is that IRepository is an interface that you create and that you make your Repositories inherit from. It gives you a reliable class hierarchy to work with.
I generally use a generic IRepository:
IRepository
Where TEntity is, well, an entity. The code I use is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wingspan.Web.Mvc
{
public interface IRepository<TEntity> where TEntity : class
{
List<TEntity> FetchAll();
IQueryable<TEntity> Query {get;}
void Add(TEntity entity);
void Delete(TEntity entity);
void Save();
}
}
A concrete implementation of this interface would be:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using Wingspan.Web.Mvc;
namespace ES.eLearning.Domain
{
public class SqlRepository<T> : IRepository<T> where T : class
{
DataContext db;
public SqlRepository(DataContext db)
{
this.db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
db.SubmitChanges();
}
#endregion
}
}
This allows me to write:
SqlRepository<UserCourse> UserCoursesRepository = new SqlRepository<UserCourse>(db);
Where db is a DataContext instance injected into, say, a Service.
With UserCoursesRepository I can now write methods in my Service class like:
public void DeleteUserCourse(int courseId)
{
var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single();
UserCoursesRepository.Delete(uc);
UserCoursesRepository.Save();
}
And now in my controllers, I can just write:
MyService.DeleteUserCourse(5);
MyService.Save();
With this pattern the development of your app becomes more of an assembly line that leads up to a VERY simple controller. Every piece of the assembly line can be tested independently of everything else, so bugs are nipped in the bud.
If this is a long, unwieldy answer it is because the real answer is:
Buy Steven Sanderson's book Pro ASP.NET MVC 2 Framework and learn to think in MVC.
An IRepository is an interface you specify when you want to implement the Repository Pattern. As #Brian Ball stated, it's not part of .NET it is an interface that you create.
Developers using the Repository Pattern widely recommend the use of an interface for the implementation. For example, in the application I am developing right now, I have 5 repositories. 4 specific and 1 generic. Each one inherits from an IRepository which ensures I will not have issues down the road with differences in implementations.
As far as code examples, I'll try:
interface IRepository<T> where T : class {
IQueryable<T> Select();
}
Implemented as a generic repository:
public class Repository<T> : IRepository<T> where T : class {
public IQueryable<T> Select() {
return this.ObjectContext.CreateObjectSet<T>();
}
}
Implemented as a specialized repository:
public class EmployeeRepository : IRepository<Employee> {
public IQueryable<Employee> Select() {
return this.ObjectContext.Employees;
}
}
Both the Repository<T> and EmployeeRepository implement IRepository, however they go about performing the querying slightly differently. The generic repository has to create an object set of T before it can try to do anything.
Keep in mind that Repository<T> is supposed to be locked to the interface, where as EmployeeRepository can implement more specialized methods to accomplish more complex logic.
I hope this helps you a little.
IRepository is not a defined type in the .Net framework. Usually when you see an interface named that, the program uses the Repository Pattern ( https://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx ). Generally when people use this pattern, they will create an interface that all the repositories adhere to. There are many benefits to doing this. Some of the benefits are code de-copupling, and unit testing.
It is also common for this to be done so it can be taken advantage of with IoC ( http://en.wikipedia.org/wiki/Inversion_of_control ).
A repository is an abstraction which represents any underlying and arbitrary data store as if it were an in memory collection of objects.
This definition is morphed into a more practical form due to common practices and system limitations as a collection of objects in memory which represent some underlying and arbitrary data store, possibly a disconnected one. Under the hood the repository may be linked to a database, a flat file, an in-memory collection of objects, or whatever else you may imagine. The user of a repository doesn't care.
So an IRepository is the interface contract which defines how Api code wishes client code to interact with the repository. This often includes add, update, delete, and get contracts as for example, this very common example of a repository contract:
public interface IRepository<TEntity> where TEntity : class
{
List<TEntity> GetAll();
void Add(TEntity entity);
void Delete(TEntity entity);
void Save();
}
But I prefer to use a different interface for a few reasons.
First, you typically wont be using a repository by itself, you will probably be using it with a unit of work pattern, so the repository shouldn't have a Save() method. It might have an Update(T entity) method - but why? The object which you receive from the repository will automatically be updatable/updated just like any other object you would receive from any kind of collection of objects because you have retrieved references to the objects themselves. (For example: if your TEntity is a Person object, and you get person "Chuck", and you change his last name from "Bartowski" to "Carmichael", the repository has presumably already updated said entity. If this seems tenuous in your mind, there is nothing wrong with implementing an Update(T entity) method.)
Second, most repositories should be able to handle disconnected environments. If your solution does not have this requirement, you can still create an interface that handles disconnected scenarios and simply leave it unimplemented. Now you are ready for the future.
At last, our contract makes more sense to the true nature of a repository - a collection of objects in memory which represent some arbitrary data store, possibly a disconnected one.
public interface IRepository<TEntity> where TEntity : class
{
List<TEntity> GetAll();
List<TEntity> Get(Func<TEntity, bool> where);
void Insert(TEntity entity);
void Insert(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void Remove(IEnumerable<TEntity> entities);
void SyncDisconnected(TEntity entity, bool forDeletion = false);
void SyncDisconnected(IEnumerable<TEntity> entities, bool forDeletion = false);
}
If you define a base class for all of your entities, let's call it DomainObject, and you give it an Id field, then you can do the following:
public interface IRepository<TEntity> where TEntity : DomainObject
{
TEntity GetById(object Id);
List<TEntity> GetAll();
List<TEntity> Get(Func<TEntity, bool> where);
void Insert(TEntity entity);
void Insert(IEnumerable<TEntity> entities);
void Remove(TEntity entity);
void Remove(IEnumerable<TEntity> entities);
void SyncDisconnected(TEntity entity, bool forDeletion = false);
void SyncDisconnected(IEnumerable<TEntity> entities, bool forDeletion = false);
}
If you don't like the optional parameter forDeletion, you can add a method which allow syncing deleted objects as well:
void SyncDisconnectedForDeletion(TEntity entity);
The reason you need to do this is because in most cases, syncing disconnected objects for deletion is incompatible with syncing disconnected objects for addition or modification. (Try it. You will see for yourself the requirements for deletion against a store vary wildly from that of addition or modification). Hence, the interface should define a contract so the implementation can discern between the two.
You can implement this interface against ANY repository of ANY underlying data store, connected or disconnected, including other abstractions to underlying data stores such as Entity Framework.
All I am trying to find out the correct definition of the repository pattern.
My original understanding was this (extremely dumbed down)
Separate your Business Objects from your Data Objects
Standardize access methods in data access layer.
I have really seen 2 different implementation, and there are no formal examples online, the ones i have seen are tucked away in books.
Implementation 1 :
public Interface IRepository<T>{
List<T> GetAll();
void Create(T p);
void Update(T p);
}
public interface IProductRepository: IRepository<Product> {
//Extension methods if needed
List<Product> GetProductsByCustomerID();
}
Implementation 2 :
public interface IProductRepository {
List<Product> GetAllProducts();
void CreateProduct(Product p);
void UpdateProduct(Product p);
List<Product> GetProductsByCustomerID();
}
Notice the first is generic Get/Update/GetAll, etc, the second is more of what I would define "DAO" like.
Both share an extraction from your data entities. Which I like, but i can do the same with a simple DAO. However the second piece standardize access operations I see value in, if you implement this enterprise wide people would easily know the set of access methods for your repository.
Am I wrong to assume that the standardization of access to data is an integral piece of this pattern ? If both are correct why would one choose to do implementation 2?
Rhino has a good article on implementation 1, and of course MS has a vague definition and an example of implementation 2 is here.
I second the Fowler quote cited by oded. I want to point out that he said "collection-like" interface. How you implement the collection like interface is certainly up to you, but neither can nor should you try to hide the fact it represents a remote datasource. It therefore differs significantly from an in-memory collection, which does not need to flush changes to a remote data store. The change tracking mechanism of your ORM or your roll-your-own solution determines how transparent this can be made to the caller. Deletes usually need to be marked explicitly, inserts are discoverable (persistence by reachability) and updates sometimes need to be marked explicitly too. Combine this with the complicated dependencies of your aggregate roots and you'll see that's not very collection like.
There is no such thing as "the cannonical repository implementation".
There is a constant battle going on between the advocators of a generic repository base class and those who prefer implementing each repository on its own. While the generic implementation is appealing in simple scenarios, you will very often find it to be a very leaky abstraction. For example some of your aggregates may only be soft-deleted (cistomizable via virtual method overrides) while others may not support a delete operation at all.
Make sure you understand the implications of each approach before deciding which route to take. Greg Young has a good post on the merits of generic repositories.
https://web.archive.org/web/20090204223739/http://codebetter.com/blogs/gregyoung/archive/2009/01/16/ddd-the-generic-repository.aspx
From Martin Fowler "Patterns of Enterprise Application Architecture", the definition of the Repository Pattern is:
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
So, both approaches are correct.
I am a great fan of the generic repository pattern but I think you should strongly consider not directly inheriting from the interface as it can become a very large limitation especially since many times the code for the generic interface will be the same that it could be defined in an abstract base class that you will no longer be able to have more than 1 generic repository inside a class.
I recommend having your IProductRepository implementer access the generic IRepository<Product> through delegation and inject that in through the constructor so you can compose your class of possibly many IRepositories and group them behind a single interface in a way that makes sense.
I wrote a blog on this topic while it specifically references NHibernate this pattern can be applied to any type of repository: Creating a common generic and extensible NHiberate Repository version 2
With the introduction of LINQ in .NET, a generic repository pattern becomes much easier to realize:
public interface IRepository<T> : IQueryable<T>
{
void Add(T item);
void Remove(T item);
}
To qualify as a repository, it merely needs to be able to access data in the underlying store (easily provided by IQueryable) and modify the contained data.
You can provide extensions to the base interface to provide hooks for more entity-specific behaviour (such as wiring into a stored procedure call for a SQL-based repository), but the majority of operations can be completed by the simple interface.
In addition to your generic repository interface (implementation 1) and your variation on the role-specific repository (implementation 2) you can also consider a generic method repository:
public interface IRepository
{
void Save<ENTITY>(ENTITY entity) where ENTITY : DomainEntity;
ENTITY Load<ENTITY>(Guid id) where ENTITY : DomainEntity;
IQueryable<ENTITY> Query<ENTITY>() where ENTITY : DomainEntity;
IQueryable<ENTITY> Query<ENTITY>(IDomainQuery<ENTITY> whereQuery)
where ENTITY : DomainEntity;
}
This third version comes from this blogpost by Jimmy Bogard, where he also expresses preference for the generic repository interface.
I usually follow that with a generic repository baseclass which implements this interface; that way, I only have to implement the stuff that is different for each domain entity.
I usually use the generic repository with composition instead of inheritance. That gives me the advantage of a generic implementation, with the control of which methods to expose.
Something like this:
public Interface IRepository<T>{
List<T> GetAll();
void Create(T p);
void Update(T p);
}
public interface IProductRepository {
//Extension methods if needed
List<Product> GetProductsByCustomerID();
List<T> GetAll();
void Create(T p);
//Let assume here you should not be able to update the products
}
public ProductRepository : IProductRepository {
private IRepository _repository;
public ProductRepository(IRepository repository) {
this._repository = repository;
}
List<T> GetAll()
{
_repository.GetAll();
}
void Create(T p)
{
_repository.Create(p);
}
List<Product> GetProductsByCustomerID()
{
//..implementation goes here
}
}
The repository pattern is one of the most used pattern in software development. The are many post that can be marked as answer to your question.
Something that i like to highlight is the fact that a good repository implementation will be improved if you use IoC (Autofac, Windsor, etc...). I have been playing long time ago with some ADO.NET based frameworks (LinqToSql, EF) and NHibernate. You always can have benefits from a generic implementation if you use IoC.
You can define interfaces for your specific repositories and resolve when you really need some specific actions.