I am making a generic repository but for some entities I also need functionalities not provided by the generic repository. I have an interface IGenericRepository and concrete implementation as GenericRepository with basic CRUD operations. Further I have a studentRepository that uses the generic repository but also has functionalities of its own independent from the Generic Repository for which i have an Interface called IStudentRepository.
Here is the sample code:
public interface IGenericEntityRepository<T>
{
Delete(T entity);
T Get(int id);
IEnumerable<T> GetAll();
Add(T entity);
Update(T entity);
}
public class GenericEntityRepository<T> : IGenericEntityRepository<T> where T : class
{
protected readonly ApplicationDbContext _applicationDbContext;
public GenericEntityRepository(ApplicationDbContext applicationDbContext)
{
this._applicationDbContext = applicationDbContext;
}
//Generic Repository Implementations....
}
public interface IStudentRepository
{
string GetFullName(Student student)
double GetGpa(Student student)
}
public class StudentRepository: GenericRepository<Student>, IStudentRepository
{
public StudentRepository(ApplicationDbContext applicationDbContext) : base(applicationDbContext)
{}
//IStudentRepository functions' implementations...
}
Now I need to inject this StudentRepository to my StudentsController
public class StudentsController : Controller
{
private readonly IGenericEntityRepository<Student> _genericStudentRepository;
public StudentsController(IGenericEntityRepository<Student> _genericStudentRepository)
{
this._genericStudentRepository = genericRepository;
}
public void testAccessibility()
{
this._genericStudentRepository.GetAll() //valid call
this._genericStudentRepository.GetAllGpa() //invalid Call
***As expected cause IGenericEntityRepository doesn't have that ***function
}
}
As you can see the probelem here, if I inject IGenericEntityRepository I only get the genericrepository functionalities. If i want the functionalities of Student repository not included in genericRepository I have to inject both IGenericEntityRepository and IStudentRepository like below and vice versa.
public class StudentsController : Controller
{
private readonly IGenericEntityRepository<Student> _genericStudentRepository;
private readonly IStudentRepository _studentsRepository;
public StudentsController(IGenericEntityRepository<Student> _genericStudentRepository, IStudentRepository studentsRepository)
{
this._genericStudentRepository = genericRepository;
this.__studentsRepository = studentsRepository;
}
public void testAccessibility()
{
this._genericStudentRepository.GetAll() //valid call
this._studentsRepository.GetAllGpa() //valid call
}
}
Is there a better way to do this? Doesn't feel right injecting two contextually same but coding wise different objects like this.
You can have IStudentRepository extend IGenericEntityRepository<T>:
public interface IStudentRepository : IGenericEntityRepository<Student>
{
string GetFullName(Student student)
double GetGpa(Student student)
}
Now injecting IStudentRepository should be enough to use all the functions.
aLets have a simple scenario:
public interface IMember
{
string Name { get; set; }
}
public class MemberEF6Impl : IMember
{
//some annotations...
public string Name { get; set; }
}
public class MemberVMImpl : IMember
{
//some other annotations...
public string Name { get; set; }
//some functionality...
}
I have two concrete implementation of all interfaces in our programm. One implementation especially for database migration, one for our viewmodel. Now I want to realize the factory-pattern and add one more interface and two more concrete implementations of it:
public interface IRepository
{
ICollection<TModel> GetAll<TModel>() where TModel : class;
//some more functionality...
}
public class RepositoryEF6Impl : IRepository
{
protected readonly DbContext context;
public RepositoryEF6Impl(DbContext context)
{
this.context = context;
}
public ICollection<TModel> GetAll<TModel>() where TModel : class
{
return context.Set<TModel>().ToList();
}
//some more functionality...
}
Now I can use the repository straight forward as follows:
IRepository repo = new RepositoryEF6Impl(context);
repo.GetAll<MemberEF6Impl>();
So far so good. But I want to use it this way:
IRepository repo = new RepositoryEF6Impl(context);
repo.GetAll<IMember>(); //note the difference
The problem is that in the database there is no IMember, but a MemberEF6Impl.
Why I want to use it this way:
Because we have different concrete classes for databse stuff and for viewmodel, I have to create a 2nd repository as well for viewmodel, which is only a layer between the concrete VMImpl class and the EF6 repository.
public class RepositoryVMImpl : IRepository
{
protected readonly IRepository repository;
public RepositoryVMImpl(IRepository repository)
{
this.repository = repository;
}
public ICollection<TModel> GetAll<TModel>() where TModel : class
{
return repository.GetAll<TModel>();
}
}
Is there a way to achive this?
My suggestion is to use single repository, but with some method overloading for projecting the requested generic type.
Method overload:
public ICollection<TProjection> GetAll<TModel, TProjection>(Expression<Func<TModel, TProjection>> projection)
{
return context.Set<TModel>().Select(projection).ToList();
}
then you can use the method like this, which will give control over the return type.
repository.GetAll<MemberEF6Impl, IMember>(memberEF => new MemberVMImp { ... })
If you still need the EF entity model as a result type you can use your current method:
repository.GetAll<MemberEF6Impl>();
More information about EF projections: https://www.tektutorialshub.com/projection-queries-entity-framework/
Also Automapper provides such functionality - it can save you some time. You should check it out.
If I have the following Context :
public partial class HRMainDataCTX : DbContext
{
public HRMainDataCTX()
: base("name=HRMainDataCTX")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
//DbSets
public virtual int SEARCHEMPLOYEE(Nullable<decimal> p_EMP_NUM, string p_EMP_NAME)
{
var p_EMP_NUMParameter = p_EMP_NUM.HasValue ?
new ObjectParameter("P_EMP_NUM", p_EMP_NUM) :
new ObjectParameter("P_EMP_NUM", typeof(decimal));
var p_EMP_NAMEParameter = p_EMP_NAME != null ?
new ObjectParameter("P_EMP_NAME", p_EMP_NAME) :
new ObjectParameter("P_EMP_NAME", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("SEARCHEMPLOYEE", p_EMP_NUMParameter, p_EMP_NAMEParameter);
}
}
Now i implement Unit of work like this :
public class HRCTX : IDisposable
{
private readonly HRMainDataCTX _context;
public HRCTX()
{
_context = new HRMainDataCTX();
}
public HRCTX(HRMainDataCTX context)
{
_context = context;
}
public int Save()
{
return _context.SaveChanges();
}
public HRMainDataCTX Context
{
get { return _context; }
}
public void Dispose()
{
_context.Dispose();
}
}
I don't know how to access the method (stored procedure) SEARCHEMPLOYEE through UOW in my code behind.
Well, in your case you would simply add another "Proxy-Method" for this method to your HRCTX proxy / UOW class, or - since HRCTX provides access to its underlying context - call it directly on the context like this:
HRCTX uow = new HRCTX(someContext);
uow.Context.SEARCHEMPLOYEE(123, "123");
But I also wanted to emphasize that the DbContext already represents a Unit of Work pattern (combined with a Repository pattern, see here). You are basically creating a proxy for your context, which - as far as I can see in this example - adds no further benefits or functionality, so I'd suggest to at least think about directly using your HRMainDataCTX and possibly getting rid of the HRCTX class.
You may need to implement repositories along with your Unit Of work pattern if you want to encapsulate your DbContext and your business logic. (As suggested in the AspNet guidelines)
In a generic manner, your unit of work can handle repositories like this:
public class HRCTX : IDisposable
{
private readonly HRMainDataCTX _context;
private Dictionary<Type, object> Repositories { get; set; }
public HRCTX()
{
_context = new HRMainDataCTX();
this.Repositories = new Dictionary<Type, object>();
}
//Get and add a repository to the dictionary if ot does not exist
public IRepository<TEntity> GetNonGenericRepository<TEntity, TRepository>() where TEntity : class
{
if (this.Repositories.Keys.Contains(typeof(TRepository)))
{
return this.Repositories[typeof(TRepository)] as IRepository<TEntity>;
}
var repoType = typeof(TRepository);
var constructorInfo = repoType.GetConstructor(new Type[] { typeof(DbContext)});
IRepository<TEntity> repository = (IRepository<TEntity>) constructorInfo.Invoke(new object[] { this._context});
this.Repositories.Add(typeof(TRepository), repository);
return repository;
}
public IRepository<TEntity> GetGenericRepository<TEntity>() where TEntity : class
{
if (this.Repositories.Keys.Contains(typeof(TEntity)))
{
return this.Repositories[typeof(TEntity)] as IRepository<TEntity>;
}
IRepository<TEntity> repository = new Repository<TEntity>(this._context);
this.Repositories.Add(typeof(TEntity), repository);
return repository;
}
}
The interface and base class of your repositories:
public interface IRepository<TEntity> where TEntity : class
{
TEntity Find(Expression<Func<TEntity, bool>> match);
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DbContext Context { get; set; }
public Repository(DbContext context)
{
this.Context = context;
}
public TEntity Find(Expression<Func<TEntity, bool>> match)
{
return Context.Set<TEntity>().SingleOrDefault(match);
}
}
Now is the part where you clearly encapsulate your business logic:
public class EmployeeRepository : Repository<Employee>
{
public EmployeeRepository(DbContext context) : base(context) {
}
public override Employee Find(Expression<Func<TEntity, bool>> match)
{
// You can either use the base class method or implement your custom logic
}
//This is where you encapsulate your business logic
public Employee FindSpecific(Nullable<decimal> employeeNum, string employeeName){
return this.Context.SEARCHEMPLOYEE(employeeNum, employeeName);
}
}
Then you can use your Unit Of Work to access you business logic in a domain driven design way.
HRCTX unitOfWork= new HRCTX(dbContext);
unitOfWork.GetNonGenericRepository<Employee, EmployeeRepository>().FindSpecific(1337,"1337");
It can seem to be too much for what you expected as an answer but I think you need to structure your application that way if you don't want to expose you DbContext / Dal directly.
Hope it helps !
This webpage documents exactly how to accomplish your goal.
http://www.asp.net/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
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 have read a bit about constraints and am trying to implement it in my repository pattern.
I want something like the below but can't quite get it to compile.
public interface IRepository<T>
{
void GetAllData<T>();
}
//This needs to inherit from IRepository
//T has to be a model class
//V has to be a class that implements IEmployeeRepo
public interface IEmployeeRepo<T, V> where V : EmployeeRepo where T : class : IRepository<T>
{
void DoSomethingEmployeeRelated();
}
//Dont think this inheritance is correct
public class EmployeeRepo<Employee, this> : IEmployeeRepo
{
}
//My example model class
public class Employee
{
public string Name {get;set;}
}
Not sure why you have two type parameters on the Repository - what is the point?
*Here is the classic example of a .NET Repository using Generics: *
*First, the Repository Interface: *
public interface IRepository<T> where T : class
{
T FindSingle(Expression<Func<T,bool>> predicate);
IQueryable<T> FindAll(); // optional - matter of preference
void Add(T entity);
void Remove(T entity);
}
*Second, the Generic Repository Implementation (EF as the example): *
public abstract class GenericRepository<T> : IRepository<T>
{
private IObjectSet<T> _ObjectSet; // get this in via DI (for example)
public T FindSingle(Expression<T,bool>> predicate)
{
return _ObjectSet.SingleOrDefault(predicate);
}
// you can figure out how to do the other implementation methods
}
*Then, the Specific Repository (you should have one per aggregate root, and also an interface for each specific repository detailing specific methods): *
public EmployeeRepository : GenericRepository<Employee>, IRepository<Employee>
{
// all regular methods (Find, Add, Remove) inherited - make use of them
public Employee FindEmployeeByName(string name)
{
return FindAll().SingleOrDefault(x => x.Name == name);
// or you could do: return FindSingle(x => x.Name == name);
}
}
Usage:
IRepository<Employee> repository = new EmployeeRepository<Employee>();
Don't go out looking to go too crazy with generics - the only one you need is to constrain the Repository to be used by a entity that is encapsulated behind the Repository.
I simply use where T : class.
Other's use where T : IDomainAggregate or similar, to put constraints on the actual type of entity which is allowed.
In this situation i usually have a base repo class that implements IRepository<>, and is typed to a base Model class.
public interface IRepository<T> where T : IModel
{
void GetAll<T>();
void GetById<T>(int id);
}
public interface IEmployeeRepo<T> : IRepository<T> where T : IModel
{
void DoSomethingEmployeeRelated();
}
public class BaseRepo : IRepository<T> where T : IModel
{
public void GetAll<T>()
{
}
public void GetById<T>(int id)
{
}
}
public class EmployeeRepo : BaseRepo<Employee>, IEmployeeRepo<Employee>
{
public void DoSomethingEmployeeRelated()
{
}
}
//My example model class
public class Employee : IModel
{
public int Id {get;set;}
public string Name {get;set;}
}
Try this;
public interface IRepository<T>
{
void GetAllData<T>();
}
//This needs to inherit from IRepository
//T has to be a model class
//V has to be a class that implements IEmployeeRepo
public interface IEmployeeRepo<T, V> : IRepository<T> where V : EmployeeRepo where T : class
{
void DoSomethingEmployeeRelated();
}
//Dont think this inheritance is correct
public class EmployeeRepo : IEmployeeRepo<Employee, EmployeeRepo>
{
public void DoSomethingEmployeeRelated()
{
}
public void GetAllData<Employee>()
{
}
}
//My example model class
public class Employee
{
public string Name {get;set;}
}