I am implementing the Repository Pattern with Entity Framework 5.0 - at least i think i am :). This is what i am using
public abstract class GenericRepository<C, T> :
IGenericRepository<T>
where T : class
where C : DbContext, new()
{
private bool disposed = false;
private C _entities = new C();
protected C Context
{
get { return _entities; }
set { _entities = value; }
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = _entities.Set<T>();
return query;
}
public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = _entities.Set<T>().Where(predicate);
return query;
}
public virtual void Add(T entity)
{
_entities.Set<T>().Add(entity);
}
public virtual void Delete(T entity)
{
_entities.Set<T>().Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = System.Data.EntityState.Modified;
}
public virtual bool Save()
{
return (_entities.SaveChanges() > 0);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
if (disposing)
_entities.Dispose();
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Afterwards this class is inherited by specific repository class - let's say PlaceRepository
public class PlaceRepository : GenericRepository<DbEntities, Place>, IPlaceRepository
{ }
In another layer (business layer) i am creating instances of the PlaceRepository class - in class called PlaceController. This class has specific methods for the PlaceEntity (CRUD). In this PlaceController i have one method that is used for inserting Place entity in the database, but at the same time i am inserting something in another table (let's say Country table). For CRUD operations over the Country table i have another Repository called CountryRepository.
To sum up, my method in the Place Controller creates instances of two different repositories, to use their methods, thereby creating two different contexts of DbContext. See code below
public class PlaceController
{
public bool InsertPlace(Place toInsert)
{
PlaceRepository _placeRepo = new PlaceRepository();
_placeRepo.Add(toInsert);
Country _country = new Country();
_country.Name = "default";
CountryRepository _countryRepo = new CountryRepository();
_countryRepo.Add(_country);
//now i must call save on bothRepositories
_countryRepo.Save(); _placeRepo.Save();
}
}
I need an opinion for this scenario. Is it good to create 2 instances of the context class to make two insertions? If it isn't should i consider using/implementing another pattern?
You should use IoC(DI) containers for that. That will help you to use 1 instance of the context whole a long the project. You can look also to the way of serviceLocator pattern but I would recoment to use IoC(DI) container. I like Castle.Windsor(the realization of DI pattern) also you can look to Ninject.
Related
I have a solution which contains several UI projects and a bunch of common (shared) DLL projects. There also is a "DB access project" based on EF which contains the models and DbContext and is referenced by the UI projects.
The problem now is, that for each UI project that uses the DbContext from the "DB access project" I have to install the Entity Framework NuGet package. The problem gets worse when I have to update EF. Then I always have to take care that all projects using EF have installed the same EF version.
Is there a better solution? The correct way for me seems to only have to install EF in one place, the "DB access project".
I also thought about something like hiding EF and the DbSets behind proxy objects only to avoid references to EF.
When I omit the EF reference I get errors like
Error CS0012 The type 'DbContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
and
Error CS0012 The type 'DbSet<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Why do you want to expose the DbContext from the DAL Layer ? The DAL layer should ideally expose a class which uses the Dbcontext or Dbset. There shoudn't be any EF depdendencies on your UI Layer. There are multiple ways to achieve this. One commonly used pattern is called Repository Pattern.
You can see the E,g here
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Your problem is typically an example that shows why it isn't wise to expose the insides of your database to the outer world.
You should expose the sequences of data on which your uses want to be able to perform Linq statements. Usually it is enough to expose the classes of your DbSets of your DbContext as IQueryable collections. This is quite often called the Repository pattern.
If you hadn't a repository, then users would create an object of your DbContext class. Then they would use the DbSets of the DbContext to access your tables as IQueryable. Use these IQueryables to create and execute the queries, possibley use SaveChanges. Finally they would Dispose the DbContext,.
The repository is used similarly. Users of your Repository would create a Repository object. Access IQueryables that represent your tables. Perform the linq, possibley SaveChanges and Dispose the Repository.
If you only want to allow queries, expose IQueryable objects, if you want to be able To Add / Update / Remove fetched items, also add Add / Remove / SaveChanges functions.
If you expose these functions as interfaces, you can unit test your code by simply replacing your DbContext by an in-memory unit-test database, or sometimes just by using Lists.
For example a School context with Students, Teachers, Grades: Teachers have many Students; Students have many Teachers (many-to-many); Students have zero or more Grades, every Grade belongs to exactly one student (one-to-many).
All items in the School context are identified by an Id: they all implement IId. This is used to enable a generic class to fetch your items by Id
Queries only
Your DbContext with the interfaces:
interface IId
{
public int Id {get;}
}
class Teacher : IId {...}
class Student: IId {...}
class Grade: IId {...}
interface ISchoolQuerier
{
IQueryable<Teacher> Teachers {get; }
IQueryable<Student> Students {get;}
IQueryable<Grade> Grades {get;}
}
class SchoolDbContext : DbContext
{
public DbSet<Teacher> Teachers {get; set;}
public DbSet<Student> Students {get; set;}
public DbSet<Grades> {get; set;}
// explicit interface implementation
IQueryable<Teacher> ISchoolQuerier.Teachers {get{return this.Teachers;}}
IQueryable<Student> ISchoolQuerier.Students {get{return this.Students;}}
IQueryable<Grade> ISchoolQuerier.Grades{get{return this.Grades;}}
}
The SchoolRepository that uses this SchoolDbContext
class SchoolRepository : IDisposable, ISchoolQuerier
{
private SchoolRepository() : this (ISchoolQuerier)(new SchoolDbContext())
{ // default constructor used default SchoolDbContext
}
private SchoolRepository(ISchoolQuerier querier)
{ // use the provided querier
// this constructor is useful for unit tests
this.querier = querier;
}
private bool isDisposed = false;
private readonly ISchoolQuerier;
#region IDisposable
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (disposing && !this.isDisposed)
{
IDisposable disposableSchool = this.SchoolQuerier as IDisposable;
if (disposableSchool != null)
{
this.schoolDbContext.Dispose();
}
this.isDisposed = true;
}
}
#endregion IDispose
#region ISchoolQuerier
public IQueryable<Teacher> Teachers {get{return this.SchoolDbContext.Teachers;}}
public IQueryable<Student> Students {get{return this.SchoolDbContext.Students;}}
public IQueryable Grades {get{return this.SchoolDbContext.Grades;}}
#endregion ISchoolQuerier
}
Users would use it similar to how they would use the SchoolContext:
using (var schoolRepository = new SchoolRepository())
{
var youngStudents = schoolRepository.Students
.Where(student => student.Birthday > ...)
.Select(student => new {...});
}
The SchoolRepository has two constructors. The default constructor uses the default DbContext. The other constructor uses the provided ISchoolQuerier. This other constructor can be useful for unit tests, where you can provide a class with three collections to test simple queries
If you only expose the interface ISchoolQuerier to users, then they don't have to install entity framework. You are also free to change internally how you access your database. Don't fancy entity framework anymore? Go ahead, use Dapper from now on, users won't notice the difference!
Change the database
If you want to add / update / delete items it consider creating a separate interface for it. Only those who have that interface can update / delete items.
Here I used the earlier defined IId
interface IChangeableSet<T> : IQueryable<T> : where T: IId
{
public T Get(int id)
public T Add(T item);
public T Remove(int Id);
public T Remove(T item);
}
class DbSet<T> : IChangeableSet<T> : where T: IId
{
public DbSet(System.Data.Entity.IDbset<T> dbSet)
{
this.dbset = dbSet
}
private readonly System.Data.Entity.IDbSet<T> dbSet;
public T Get(int id)
{
return this.DbSet.Where(item => item.Id == id).SingleOrDefault();
// here is where I uses that all items implement IId
}
public T Add(T item)
{
return this.dbSet.Add(item);
}
... // TODO: fill the other functions
}
The SchoolRepository implements this interface (preferrably explicit implementatin)
class ChangeableSchoolRepository : IDisposable, ISchoolQuerier
{
public ChangeableSchoolRepository(SchooldDbContext dbContext)
{
this.schoolDbContext = dbContext;
}
private readonly SchoolDbContext;
public IChangeableSet<Teacher> Teachers
{
get {return new DbSet(dbContext.Teachers);}
}
... // etc for Students / Grades
public void SaveChanges()
{
return this.SchoolDbcontext.SaveChanges();
}
}
I now use the following solution. In general, I encapsulated the functionality of EF and IQueryable that I require in three proxy objects.
Instead of using the EF DbContext directly, I now use a proxy object (the DataStore class) that offers me the DbSets (repositories).
The EF DbSets exposed by the DbContext I wrapped into a generic Repository, which exposes the functionality required to work with the data. The Repository itself is derived from DbQueryProxy which proxies the EF DbQuery.
Now I can comfortably work with the data in a familiar way:
using (var db = new DataStore())
{
var students = db.Students.DoSomeLinq(...);
var teachers = db.Teachers.SomeLinq(...);
// do some work ...
// note: The entities in students and teachers are still bound to the DbContext internal to DataStore!
// optional
db.SaveChanges();
}
DataStore:
public class DataStore : IDisposable
{
private readonly DbContext _dbContext;
#region constructors
public DataStore()
{
_dbContext = new DbContext();
}
#endregion constructors
internal DbContext Context => _dbContext;
public void RemoveRange<TEntity>(IEnumerable<TEntity> entities) where TEntity : EntityBase => _dbContext.RemoveRange(entities);
#region db sets
public Repository<Teacher> Teachers => _dbContext.Teachers; // implicit type conversion from DbSet<TEntity> to Repository<TEntity>!
public Repository<Student> Students => _dbContext.Students;
public Repository<Grade> Grades => _dbContext.Grade;
#endregion db sets
#region DbContext
public void Dispose() => _dbContext.Dispose();
public int SaveChanges() => _dbContext.SaveChanges();
public Repository<TEntity> Set<TEntity>() where TEntity : EntityBase => _dbContext.Set<TEntity>();
public override bool Equals(object obj) => _dbContext.Equals(obj);
public override int GetHashCode() => _dbContext.GetHashCode();
public override string ToString() => _dbContext.ToString();
#endregion DbContext
}
Repository<TEntity>:
public class Repository<TEntity> : DbQueryProxy<TEntity> where TEntity : class
{
private readonly DbSet<TEntity> _DbSet;
internal Repository(DbSet<TEntity> dbSet) : base(dbSet)
{
_DbSet = dbSet;
}
private Repository()
{
}
public static implicit operator DbSet<TEntity>(Repository<TEntity> entry) => entry._DbSet;
public static implicit operator Repository<TEntity>(DbSet<TEntity> entry) => new Repository<TEntity>(entry);
#region DbSet<TEntity>
public TEntity Add(TEntity entity) => _DbSet.Add(entity);
public IEnumerable<TEntity> AddRange(IEnumerable<TEntity> entities) => _DbSet.AddRange(entities);
public TEntity Attach(TEntity entity) => _DbSet.Attach(entity);
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, TEntity => _DbSet.Create<TDerivedEntity>();
public override bool Equals(object obj) => _DbSet.Equals(obj);
public override int GetHashCode() => _DbSet.GetHashCode();
public TEntity Find(params object[] keyValues) => _DbSet.Find(keyValues);
public Task<TEntity> FindAsync(params object[] keyValues) => _DbSet.FindAsync(keyValues);
public Task<TEntity> FindAsync(CancellationToken cancellationToken, params object[] keyValues) => _DbSet.FindAsync(cancellationToken, keyValues);
public TEntity Remove(TEntity entity) => _DbSet.Remove(entity);
public IEnumerable<TEntity> RemoveRange(IEnumerable<TEntity> entities) => _DbSet.RemoveRange(entities);
#endregion DbSet<TEntity>
}
DbQueryProxy<TEntity>:
public class DbQueryProxy<TResult> : IOrderedQueryable<TResult>, IListSource
{
private readonly DbQuery<TResult> _DbQuery;
internal DbQueryProxy(DbQuery<TResult> entry)
{
_DbQuery = entry;
}
protected DbQueryProxy()
{
}
public static implicit operator DbQuery<TResult>(DbQueryProxy<TResult> entry) => entry._DbQuery;
public static implicit operator DbQueryProxy<TResult>(DbQuery<TResult> entry) => new DbQueryProxy<TResult>(entry);
#region Interfaces
Type IQueryable.ElementType => ((IQueryable)_DbQuery).ElementType;
Expression IQueryable.Expression => ((IQueryable)_DbQuery).Expression;
IQueryProvider IQueryable.Provider => ((IQueryable)_DbQuery).Provider;
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_DbQuery).GetEnumerator();
IEnumerator<TResult> IEnumerable<TResult>.GetEnumerator() => ((IEnumerable<TResult>)_DbQuery).GetEnumerator();
bool IListSource.ContainsListCollection => ((IListSource)_DbQuery).ContainsListCollection;
IList IListSource.GetList() => ((IListSource)_DbQuery).GetList();
#endregion Interfaces
#region DbQuery<TResult>
public string Sql => _DbQuery.Sql;
public DbQueryProxy<TResult> AsNoTracking() => _DbQuery.AsNoTracking();
public override bool Equals(object obj) => _DbQuery.Equals(obj);
public override int GetHashCode() => _DbQuery.GetHashCode();
public DbQueryProxy<TResult> Include(string path) => _DbQuery.Include(path);
public override string ToString() => _DbQuery.ToString();
#endregion DbQuery<TResult>
}
I use EF in my project and I want to implement the repository design pattern, but I want to have one super class which will take care for the Insert / Update / Delete / SaveChanges methods in order to avoid code duplication.
For example, I have these two interfaces ICostTypeRepository and IEmailRepository:
public interface ICostTypeRepository : IDisposable
{
CostType GetCostTypeById(int pId);
CostType GetCostTypeByCode(string pCode);
IEnumerable<CostType> GetCostTypes();
void Insert(CostType pCostType);
void Update(CostType pCostType);
void Delete(CostType pCostType);
void SaveChanges();
}
public interface IEmailRepository : IDisposable
{
Email GetEmailByID(int pId);
IEnumerable<Email> GetEmails();
Email GetEmailByAdress(string pAddress);
void Insert(Email pEmail);
void Update(Email pEmail);
void Delete(Email pEmail);
void SaveChanges();
}
What is the best way of creating an interface (and its implementation in a class) let's call it IDbOperations which will contain the CRUD methods only?
Something like
public interface IDbOperations : IDisposable
{
void Insert(??);
void Update(??);
void Delete(??);
void SaveChanges();
}
What parameters will these CRUD methods take?
Vane,
What you need is the generic repository pattern. You have to code the basic operations in a base class and then make extend all the repository classes from it. Inside each new repository class you can create more specific methods.
This is an example of a Generic Repository interface
public interface IGenericRepository<T> where T : class {
IQueryable<T> GetAll();
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Edit(T entity);
void Save();
}
You can implement the generic repository like this:
public class GenericRepository<C, T> :
IGenericRepository<T> where T : class where C : DbContext, new() {
private C _entities = new C();
public C Context {
get { return _entities; }
set { _entities = value; }
}
public virtual IQueryable<T> GetAll() {
IQueryable<T> query = _entities.Set<T>();
return query;
}
public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate) {
IQueryable<T> query = _entities.Set<T>().Where(predicate);
return query;
}
public virtual void Add(T entity) {
_entities.Set<T>().Add(entity);
}
public virtual void Delete(T entity) {
_entities.Set<T>().Remove(entity);
}
public virtual void Edit(T entity) {
_entities.Entry(entity).State = System.Data.EntityState.Modified;
}
public virtual void Save() {
_entities.SaveChanges();
}
}
Now that you have the GenericRepository class, make FooRepository extend it and add specific methods (if needed) like this:
public class FooRepository :
GenericRepository<FooBarEntities, Foo>, IFooRepository {
public Foo GetSingle(int fooId) {
var query = GetAll().FirstOrDefault(x => x.FooId == fooId);
return query;
}
}
You should read about Unit of work pattern. It makes a lot of sense with the repository pattern. Please read this article from Microsoft.
I've found that in my UnitOfWork I have a repository for each type of entity and am not using aggregate roots, so I'm trying to fix that. Tackling the idea of computer inventory, I currently have my UnitOfWork structured as such:
public class UnitOfWork : IUnitOfWork
{
private readonly ReportingDbContext _dbContext = null;
public UnitOfWork()
{
_dbContext = new ReportingDbContext();
}
public void Commit()
{
_dbContext.SaveChanges();
}
// Inventory
public IRepository<ComputerEntity> Computers {get { return new Repository<ComputerEntity>(_dbContext); }}
public IRepository<NetworkAdapterEntity> NetworkAdapters { get { return new Repository<NetworkAdapterEntity>(_dbContext); } }
// plus a bunch more
}
I want only my aggregate root to appear there, which should be easy enough to do. I think the issue is that I'm using a single repository class and feeding in the type when I new it up. I believe the answer is to have multiple repositories, each one corresponding to an aggregate root. What is nice about this one generic repository that I'm using for each type is that it handles all my Entity Framework stuff like finding by ID, saving to the DbSet, etc. My generic repository is setup as such:
public class Repository<T> : IRepository<T> where T : class
{
protected DbContext DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public Repository(DbContext dbContext)
{
if (dbContext == null)
{
throw new ArgumentNullException("dbContext");
}
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
public IQueryable<T> GetAll()
{
return DbSet;
}
public IQueryable<T> Find(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
// the rest of the implementation omitted for brevity
}
This repository uses an interface that all my yet-to-be-created aggregate root repositories should use:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
T GetById(int id);
void Remove(T entity);
void Add(T newEntity);
}
Now here is the real meat of the question. I have the above interface implemented nicely in my concrete Repository class, and I want that same functionality in all the aggregate root repositories that I will be making. I don't want to ever directly use this generic repository, as I just want to use it for a base to get at the basic CRUD stuff it does with Entity Framework. I don't want to repeat the already implemented generic repository stuff, just inherit it. More importantly, I want to design this correctly the first time.
Would it be appropriate to create my aggregate root based repository as such:
public interface IComputerRepository
{
string ComputerSpecificMethod(string param);
}
public class ComputerRepository : Repository<ComputerEntity>, IComputerRepository
{
public ComputerRepository(DbContext dbContext) : base(dbContext)
{
//
}
public string ComputerSpecificMethod(string param)
{
// do stuff
return "test";
}
}
Then use this new fancy repository (and others like it) in my UnitOfWork as such:
public IRepository<ComputerEntity> Computers {get { return new ComputerRepository(_dbContext); }}
Instead of:
public IRepository<ComputerEntity> Computers {get { return new Repository<ComputerEntity>(_dbContext); }}
The goal is to stick to the UnitOfWork/Repository pattern, and I'm unsure if this is the proper way of doing this.
I found that the way to do this that works for me is to have the interface for each custom repository in my unit of work class as such:
public IInventoryRepository Computers { get { return new InventoryRepository(_dbContext); } }
It is implemented in its own class of course. To get it to inherit properly, I did this:
public class InventoryRepository : GenericRepository<ComputerEntity>, IInventoryRepository
{
public InventoryRepository(DbContext dbContext) : base(dbContext)
{
}
// your custom methods go here
}
I then can use this in my WCF service as such:
using (var uoW = new UnitOfWork())
{
var repo = uoW.Computers;
var computerEntity = repo.FindComputerByHostname(hostname, client);
// do more stuff
}
Context / Question
I've worked on numerous .NET projects that have been required to persist data and have usually ended up using a Repository pattern. Does anyone know of a good strategy for removing as much boilerplate code without sacrificing code base scalability?
Inheritance Strategy
Because so much of the Repository code is boiler plate and needs to be repeated I normally create a base class to cover the basics like exception handling, logging and transaction support as well as a few basic CRUD methods:
public abstract class BaseRepository<T> where T : IEntity
{
protected void ExecuteQuery(Action query)
{
//Do Transaction Support / Error Handling / Logging
query();
}
//CRUD Methods:
public virtual T GetByID(int id){}
public virtual IEnumerable<T> GetAll(int id){}
public virtual void Add (T Entity){}
public virtual void Update(T Entity){}
public virtual void Delete(T Entity){}
}
So this works well when I have a simple domain, I can quickly create a DRY repository class for each entity. However, this starts to break down when the domain gets more complex. Lets say a new entity is introduced that does not allow updates. I can break up base classes and move the Update method into a different class:
public abstract class BaseRepositorySimple<T> where T : IEntity
{
protected void ExecuteQuery(Action query);
public virtual T GetByID(int id){}
public virtual IEnumerable<T> GetAll(int id){}
public virtual void Add (T entity){}
public void Delete(T entity){}
}
public abstract class BaseRepositoryWithUpdate<T> :
BaseRepositorySimple<T> where T : IEntity
{
public virtual void Update(T entity){}
}
This solution does not scale well. Let's say I have several Entities that have a common method:
public virtual void Archive(T entity){}
but some Entities that can be Archived can also be Updated while others can't. So my Inheritance solution breaks down, I'd have to create two new base classes to deal with this scenario.
Compoisition Strategy
I've explored the Compositon pattern, but this seems to leave a lot of boiler plate code:
public class MyEntityRepository : IGetByID<MyEntity>, IArchive<MyEntity>
{
private Archiver<MyEntity> _archiveWrapper;
private GetByIDRetriever<MyEntity> _getByIDWrapper;
public MyEntityRepository()
{
//initialize wrappers (or pull them in
//using Constructor Injection and DI)
}
public MyEntity GetByID(int id)
{
return _getByIDWrapper(id).GetByID(id);
}
public void Archive(MyEntity entity)
{
_archiveWrapper.Archive(entity)'
}
}
The MyEntityRepository is now loaded with boilerplate code. Is there a tool / pattern that I can use to automatically generate this?
If I could turn the MyEntityRepository into something like this, I think that would by far be ideal:
[Implement(Interface=typeof(IGetByID<MyEntity>),
Using = GetByIDRetriever<MyEntity>)]
[Implement(Interface=typeof(IArchive<MyEntity>),
Using = Archiver<MyEntity>)
public class MyEntityRepository
{
public MyEntityRepository()
{
//initialize wrappers (or pull them in
//using Constructor Injection and DI)
}
}
Aspect Oriented Programming
I looked into using an AOP framework for this, specifically PostSharp and their Composition Aspect, which looks like it should do the trick, but in order to use a Repository I'll have to call Post.Cast<>(), which adds a very odd smell to the code. Anyone know if there's a better way to use AOP to help get rid of the compositor boilerplate code?
Custom Code Generator
If all else fails, I suppose I could work at creating a Custom Code Generator Visual Studio plug in that could generate the boiler plate code into a partial code file. Is there already a tool out there that would do this?
[Implement(Interface=typeof(IGetByID<MyEntity>),
Using = GetByIDRetriever<MyEntity>)]
[Implement(Interface=typeof(IArchive<MyEntity>),
Using = Archiver<MyEntity>)
public partial class MyEntityRepository
{
public MyEntityRepository()
{
//initialize wrappers (or pull them in
//using Constructor Injection and DI)
}
}
//Generated Class file
public partial class MyEntityRepository : IGetByID<MyEntity>, IArchive<MyEntity>
{
private Archiver<MyEntity> _archiveWrapper;
private GetByIDRetriever<MyEntity> _getByIDWrapper;
public MyEntity GetByID(int id)
{
return _getByIDWrapper(id).GetByID(id);
}
public void Archive(MyEntity entity)
{
_archiveWrapper.Archive(entity)'
}
}
Extension Methods
Forgot to add this when I initially wrote the question (sorry). I also tried experimenting with extension methods:
public static class GetByIDExtenions
{
public T GetByID<T>(this IGetByID<T> repository, int id){ }
}
However, this has two problems, a) I'd have to remember the namespace of the extension methods class and add it everywhere and b) the extension methods can't satisfy interface dependencies:
public interface IMyEntityRepository : IGetByID<MyEntity>{}
public class MyEntityRepository : IMyEntityRepository{}
Update: Would T4 Templates be a possible solution?
I have a single generic repository interface, which is implemented only once for a particular data storage. Here it is:
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
T Get(object id);
void Save(T item);
void Delete(T item);
}
I have implementations of it for EntityFramework, NHibernate, RavenDB storages. Also I have an in-memory implementation for unit testing.
For example, here is a part of the in-memory collection-based repository:
public class InMemoryRepository<T> : IRepository<T> where T : class
{
protected readonly List<T> _list = new List<T>();
public virtual IQueryable<T> GetAll()
{
return _list.AsReadOnly().AsQueryable();
}
public virtual T Get(object id)
{
return _list.FirstOrDefault(x => GetId(x).Equals(id));
}
public virtual void Save(T item)
{
if (_list.Any(x => EqualsById(x, item)))
{
Delete(item);
}
_list.Add(item);
}
public virtual void Delete(T item)
{
var itemInRepo = _list.FirstOrDefault(x => EqualsById(x, item));
if (itemInRepo != null)
{
_list.Remove(itemInRepo);
}
}
}
Generic repository interface frees me from creating lot's of similar classes. You have only one generic repository implementation, but also freedom in querying.
IQueryable<T> result from GetAll() method allows me to make any queries I want with the data, and separate them from the storage-specific code. All popular .NET ORMs have their own LINQ providers, and they all should have that magic GetAll() method - so no problems here.
I specify repository implementation in the composition root using IoC container:
ioc.Bind(typeof (IRepository<>)).To(typeof (RavenDbRepository<>));
In the tests I'm using it's in-memory replacement:
ioc.Bind(typeof (IRepository<>)).To(typeof (InMemoryRepository<>));
If I want to add more business-specific queries for the repository, I will add an extension method (similar to your extension method in the answer):
public static class ShopQueries
{
public IQueryable<Product> SelectVegetables(this IQueryable<Product> query)
{
return query.Where(x => x.Type == "Vegetable");
}
public IQueryable<Product> FreshOnly(this IQueryable<Product> query)
{
return query.Where(x => x.PackTime >= DateTime.Now.AddDays(-1));
}
}
So you can use and mix those methods in the business logic layer queries, saving testability and easiness of repository implementations, like:
var freshVegetables = repo.GetAll().SelectVegetables().FreshOnly();
If you don't want to use a different namespace for those extension methods (like me) - ok, put them in the same namespace where repository implementation resides (like MyProject.Data), or, even better, to some existing business specific namespace (like MyProject.Products or MyProject.Data.Products). No need to remember additional namespaces now.
If you have some specific repository logic for some kind of entities, create a derived repository class overriding the method you want. For example, if products can only be found by ProductNumber instead of Id and don't support deleting, you can create this class:
public class ProductRepository : RavenDbRepository<Product>
{
public override Product Get(object id)
{
return GetAll().FirstOrDefault(x => x.ProductNumber == id);
}
public override Delete(Product item)
{
throw new NotSupportedException("Products can't be deleted from db");
}
}
And make IoC return this specific repository implementation for products:
ioc.Bind(typeof (IRepository<>)).To(typeof (RavenDbRepository<>));
ioc.Bind<IRepository<Product>>().To<ProductRepository>();
That's how I leave in piece with my repositories ;)
Checkout T4 Files for code generation. T4 is built into Visual Studio. See a tutorial here.
I have created T4 files for code generating POCO entities by inspecting a LINQ DBML and for their repositories, I think it would serve you well here. If you generate partial classes with your T4 file, you could just write code for the special cases.
To me, it seems that you divide the base classes and then want the functionality from both of them in one inheritor class. In such a case, composition is the choice. Multiple class inheritance would also be nice if C# supported it. However, because I feel the inheritance is nicer and reusability is still fine, my first option choice would go with it.
Option 1
I would rather have one more base class instead of the composition of the two. Reusability can be solved with static methods as well rather than the inheritance:
Reusable part is not visible outside. No need to remember the namespace.
static class Commons
{
internal static void Update(/*receive all necessary params*/)
{
/*execute and return result*/
}
internal static void Archive(/*receive all necessary params*/)
{
/*execute and return result*/
}
}
class Basic
{
public void SelectAll() { Console.WriteLine("SelectAll"); }
}
class ChildWithUpdate : Basic
{
public void Update() { Commons.Update(); }
}
class ChildWithArchive : Basic
{
public void Archive() { Commons.Archive(); }
}
class ChildWithUpdateAndArchive: Basic
{
public void Update() { Commons.Update(); }
public void Archive() { Commons.Archive(); }
}
Of course there's some minor repeated code, but that's just calling the ready-made functions from the common library.
Option 2
My implementation of the composition (or imitation of the multiple inheritance):
public class Composite<TFirst, TSecond>
{
private TFirst _first;
private TSecond _second;
public Composite(TFirst first, TSecond second)
{
_first = first;
_second = second;
}
public static implicit operator TFirst(Composite<TFirst, TSecond> #this)
{
return #this._first;
}
public static implicit operator TSecond(Composite<TFirst, TSecond> #this)
{
return #this._second;
}
public bool Implements<T>()
{
var tType = typeof(T);
return tType == typeof(TFirst) || tType == typeof(TSecond);
}
}
Inheritance and composition (below):
class Basic
{
public void SelectAll() { Console.WriteLine("SelectAll"); }
}
class ChildWithUpdate : Basic
{
public void Update() { Console.WriteLine("Update"); }
}
class ChildWithArchive : Basic
{
public void Archive() { Console.WriteLine("Archive"); }
}
Composition. Not sure if this is enough to say that no boilerplate code exists.
class ChildWithUpdateAndArchive : Composite<ChildWithUpdate, ChildWithArchive>
{
public ChildWithUpdateAndArchive(ChildWithUpdate cwu, ChildWithArchive cwa)
: base(cwu, cwa)
{
}
}
Code using all this looks kind of OK, but still unusual (invisible) type casts in assignments. This is a pay off for having less boilerplate code:
ChildWithUpdate b;
ChildWithArchive c;
ChildWithUpdateAndArchive d;
d = new ChildWithUpdateAndArchive(new ChildWithUpdate(), new ChildWithArchive());
//now call separated methods.
b = d;
b.Update();
c = d;
c.Archive();
Here is my version:
interface IGetById
{
T GetById<T>(object id);
}
interface IGetAll
{
IEnumerable<T> GetAll<T>();
}
interface ISave
{
void Save<T>(T item) where T : IHasId; //you can go with Save<T>(object id, T item) if you want pure pure POCOs
}
interface IDelete
{
void Delete<T>(object id);
}
interface IHasId
{
object Id { get; set; }
}
I don't like generic repository interface as it puts additional restrictions and makes it harder to work with it later. I use generic methods instead.
Instead of using header interface for repository I use role interfaces for each repository method. This lets me add additional functionality to repository methods, like logging, publishing changes to PubSub and so on.
I don't use repository for custom queries as I yet didn't find any good and simple querying abstraction that would fit any database. My version of repository can only get item by id or get all items of same type. Other queries is done in memory (if performance is good enough) or I have some other mechanism.
For convenience IRepository interface could be introduced so you would not have to constantly write 4 interfaces for something like crud controllers
interface IRepository : IGetById, IGetAll, ISave, IDelete { }
class Repository : IRepository
{
private readonly IGetById getter;
private readonly IGetAll allGetter;
private readonly ISave saver;
private readonly IDelete deleter;
public Repository(IGetById getter, IGetAll allGetter, ISave saver, IDelete deleter)
{
this.getter = getter;
this.allGetter = allGetter;
this.saver = saver;
this.deleter = deleter;
}
public T GetById<T>(object id)
{
return getter.GetById<T>(id);
}
public IEnumerable<T> GetAll<T>()
{
return allGetter.GetAll<T>();
}
public void Save<T>(T item) where T : IHasId
{
saver.Save(item);
}
public void Delete<T>(object id)
{
deleter.Delete<T>(id);
}
}
I mentioned that with role interfaces i can add additional behavior, here is couple examples using decorators
class LogSaving : ISave
{
private readonly ILog logger;
private readonly ISave next;
public LogSaving(ILog logger, ISave next)
{
this.logger = logger;
this.next = next;
}
public void Save<T>(T item) where T : IHasId
{
this.logger.Info(string.Format("Start saving {0} : {1}", item.ToJson()));
next.Save(item);
this.logger.Info(string.Format("Finished saving {0}", item.Id));
}
}
class PublishChanges : ISave, IDelete
{
private readonly IPublish publisher;
private readonly ISave nextSave;
private readonly IDelete nextDelete;
private readonly IGetById getter;
public PublishChanges(IPublish publisher, ISave nextSave, IDelete nextDelete, IGetById getter)
{
this.publisher = publisher;
this.nextSave = nextSave;
this.nextDelete = nextDelete;
this.getter = getter;
}
public void Save<T>(T item) where T : IHasId
{
nextSave.Save(item);
publisher.PublishSave(item);
}
public void Delete<T>(object id)
{
var item = getter.GetById<T>(id);
nextDelete.Delete<T>(id);
publisher.PublishDelete(item);
}
}
It's not hard to implement in memory store for testing
class InMemoryStore : IRepository
{
private readonly IDictionary<Type, Dictionary<object, object>> db;
public InMemoryStore(IDictionary<Type, Dictionary<object, object>> db)
{
this.db = db;
}
...
}
Finally put all together
var db = new Dictionary<Type, Dictionary<object, object>>();
var store = new InMemoryStore(db);
var storePublish = new PublishChanges(new Publisher(...), store, store, store);
var logSavePublish = new LogSaving(new Logger(), storePublish);
var repo = new Repository(store, store, logSavePublish, storePublish);
You can use the visitor pattern, read an implementation here so you can only implement the necesary functionality.
HereĀ“s the idea:
public class Customer : IAcceptVisitor
{
private readonly string _id;
private readonly List<string> _items = new List<string>();
public Customer(string id)
{
_id = id;
}
public void AddItems(string item)
{
if (item == null) throw new ArgumentNullException(nameof(item));
if(_items.Contains(item)) throw new InvalidOperationException();
_items.Add(item);
}
public void Accept(ICustomerVisitor visitor)
{
if (visitor == null) throw new ArgumentNullException(nameof(visitor));
visitor.VisitCustomer(_items);
}
}
public interface IAcceptVisitor
{
void Accept(ICustomerVisitor visitor);
}
public interface ICustomerVisitor
{
void VisitCustomer(List<string> items);
}
public class PersistanceCustomerItemsVisitor : ICustomerVisitor
{
public int Count { get; set; }
public List<string> Items { get; set; }
public void VisitCustomer(List<string> items)
{
if (items == null) throw new ArgumentNullException(nameof(items));
Count = items.Count;
Items = items;
}
}
So, you can apply separation of concerns between domain logic and infraestructure applying the visitor patter for persistance.
Regards!
i am pretty new to the repository design pattern and i have reached a dead end while trying to implement it, with regards to inheritance.
I am not sure even if i started in the right direction.
So basically i will have an abstract base class Product, with id and imagePath for instance, and will have several products which inherit from this.
namespace Common
{
public abstract class Product
{
public int Id { get; set; }
public string ImgPath { get; set; }
}
public class Scale : Product
{
public int AdditionalProperty { get; set; }
}
}
Now the repositories are as follows:
public class BaseRepository
{
protected TEstEntities1 _dataContext = new TEstEntities1();
public BaseRepository()
{
_dataContext = new TEstEntities1();
}
}
public interface IProductRepository
{
Common.Product Get(int id);
void Add(Common.Product p);
void Update(Common.Product p);
List<Common.Product> ListAll();
}
public class ProductRepository : BaseRepository, IProductRepository
{
public Common.Product Get(int id)
{
throw new NotImplementedException();
}
public void Add(Common.Product p)
{
throw new NotImplementedException();
}
public void Update(Common.Product p)
{
throw new NotImplementedException();
}
public List<Common.Product> ListAll()
{
throw new NotImplementedException();
}
}
My problem is as follows: how do i integrate operations regarding Scale ? It seems a bad idea to add something like Add(Common.Scale s) to the IProductRepository. It seems like a bad idea to see inside the Add(Common.Product p) which type of Product i try to add, then cast to it, then add.
I guess that if i were to describe this problem more thoroughly, I want to repeat as few code as possible, to somehow isolate base product adding/removing code in the product repository, and somehow put e.g. Scale specific code for adding/removing inside another class, or method.
A more thorough approach of mine has been this one:
public interface IProductRepository<T> where T : Common.Product
{
T Get(int id);
void Add(T p);
void Delete(T p);
}
public abstract class ProductRepository : BaseRepository
{
protected void Add(Common.Product p)
{
_dataContext.AddToProduct(new Product { Id = p.Id, Image = p.ImgPath });
_dataContext.AcceptAllChanges();
}
protected void Delete(Common.Product p)
{
var c = _dataContext.Product.Where(x => x.Id == p.Id).FirstOrDefault();
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
}
protected Product Get(int id)
{
return _dataContext.Product.Where(x => x.Id == id).FirstOrDefault();
}
}
public class CantarRepository : ProductRepository, IProductRepository<Common.Scale>
{
public void Add(Common.Scale p)
{
base.Add(p);
_dataContext.Scale.AddObject
(new Scale { ProductId = p.Id, AdditionalProperty = p.AdditionalProperty });
_dataContext.AcceptAllChanges();
}
public void Delete(Common.Scale p)
{
var c = _dataContext.Scale.Where(x => x.ProductId == p.Id);
_dataContext.DeleteObject(c);
_dataContext.AcceptAllChanges();
base.Delete(p);
}
public new Common.Scale Get(int id)
{
var p = base.Get(id);
return new Common.Scale
{
Id = p.Id,
ImgPath = p.Image,
AdditionalProperty = _dataContext.Scale.Where
(c => c.ProductId == id).FirstOrDefault().AdditionalProperty
};
}
}
Unfortunatelly this falls short for one reason.
If i use a factory pattern to return an IProductRepository and inside it i instantiate with IProductRepository this will not work because of covariance and contravariance, and IProductRepository can't be contravariant and covariant at the same time, and splitting the methods into two interfaces seems counterintuitive and cumbersome.
I suspect i will need the factory pattern in order to have a base class interface returned, but i am open to suggestions on this as well. As i've said, i am very newbie regarding the repo pattern.
I am curious as to what i am doing wrong, how i can solve this, and how can i implement this better.
Thanks.
You are using inheritance incorrectly. You cannot treat Scale as a (is-a) Product if the important difference is additional properties - that makes the exposed interface of Scale different than Product, and at that point inheritance simply gets in your way. Use inheritance to share behavior, not properties.
What problem are you trying to solve with your use of inheritance?
I want to repeat as few code as
possible
Wouldn't it be better to have a little duplication in order to get things done, rather than spin your wheels trying to work with an implausible design?
Also, this is all you are sharing with your inheritance:
public int Id { get; set; }
public string ImgPath { get; set; }
Repeating the definition of two auto-implemented properties almost doesn't even qualify as duplication, it most certainly is not an issue to be concerned about.
Misusing inheritance, however, is fairly grievous. The next person to maintain your app will curse you for it.
So basically i will have an abstract
base class Product, with id and
imagePath for instance, and will have
several products which inherit from
this.
So when you add new types of products you will have to extend an inheritance hierarchy? That seems like a bad idea.
I'm not a big fan of generic repository but after looking at your code I think you should use it:
public interface IEntity
{
int Id { get; }
}
public interface IRepository<T> where T : class, IEntity
{
IQueryable<T> GetQuery();
T Get(int id);
void Add(T entity);
void Update(T entity);
void Delete(T entity);
}
implementation:
public Repository<T> where T : class, IEntity
{
private ObjectSet<T> _set; // or DbSet
private ObjectContext _context; // or DbContext
public Repository(ObjectContext context) // or DbContext
{
_context = context;
_set = context.CreateObjectSet<T>(); // _context.Set<T>() for DbContext
}
public IQueryable<T> GetQuery()
{
return _set;
}
public T Get(int id)
{
return _set.SingleOrDefault(e => e.Id == id);
}
public void Add (T entity)
{
_set.AddObject(entity);
}
public void Update(T entity)
{
_set.Attach(entity);
context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
// or context.Entry(entity).State = EntityState.Modified; for DbContext
}
public void Delete(entity)
{
_set.Attach(entity);
_set.DeleteObject(entity);
}
}
There is NO AcceptAllChanges because it will reset ObjectStateManager and your changes will never be saved. There is no recreation of objects because it doesn't make sense.
Using this repository is as simple as:
var repo = new BaseRepository<Product>(context);
repo.Add(new Product() { ... });
repo.Add(new Scale() { ... }); // yes this works because derived entities are handled by the same set
context.Save();
I recently implemented something like this. (Using your sample types names) I have a single ProductRepository which knows how to persist/unpersist all Product subtypes.
Ultimately, your backing data store will have to have the ability to store the various subtypes and any properties which they introduce. Your repository type will also have to know how to take advantage of those features for each given subtype. Therefore, each time you add a subtype, you will have work involved in, for example, adding table columns to your backing data store to hold properties it may introduce. This implies that you will also need to make the appropriate changes to your repository type. It seems easiest, therefore, to examine the type of the entity when passed to your repository type and throw an exception if it is not a supported type since there's nothing else your repository will be able to do with it. Similarly, when retrieving the list of entities, the repository will have to know how to retrieve each entity subtype and construct an instance. Since these all derive from Product, they can all form items an in IEnumerable<Product> return value.