I have almost completed implementing my repository pattern by having a IRepository<T> interface, a NewsRepository class and a News entity. The problem I ran into was trying to abstract out common methods to a base Repository class.
I could not find a way to abstract the Get method in the NewsRepository as it contains a specific Linq expression.
My questions are:
1) How do I abstract to a base class the public T Get(int id) method please? The only way I have done it so far is by passing in Expression<Func<T,bool>> instead of an int, but then that deosn't really abstract out common behaviour as each sub-class will still need to pass in an expression that is almost identical in each case ie n => n.id == id.
2) How do I pass into the base class on the Update method the sub-class GetViolations and map methods please? I imagine the solution is possibly by using delegates, but I couldn't get the syntax to compile
This is a simplified set of the code - in practice I have a Save method which does Update and Insert rather than just the Update shown here.
public interface IRepository<T>
{
T Get(int id);
void Update(T item);
}
public class NewsRepository : IRepository<News>
{
private Table<News> _newsTable;
public NewsRepository(string connectionString)
{
_newsTable = new DataContext(connectionString).GetTable<News>();
}
public News Get(int id)
{
return _newsTable.SingleOrDefault(n => n.NewsId == id);
}
public void Update(News item)
{
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
News dbNews = _newsTable.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_newsTable.Context.SubmitChanges();
}
private void map(News dbNews, News news)
{
dbNews.Title = news.Title;
dbNews.Article = news.Article;
}
}
public class Repository<T> where T : class
{
protected Table<T> _table;
public Repository(Table<T> t)
{
_table = t;
}
//How do i do this??! - This doesn't compile due to T no having a NewsId
public T Get(int id)
{
return _table.SingleOrDefault(n => n.NewsId == id);
}
//This seems to be a solution, but it's not really abstracting common behaviour as each
//sub-class will still need to pass in the same linq expression...
public T Get(Expression<Func<T,bool>> ex)
{
return _table.SingleOrDefault(ex);
}
public void Update(T item)
{
//How is it possible to pass in the GetRuleViolations and map functions to this method?
var errors = item.GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
T dbNews = _table.SingleOrDefault(n => n.NewsId == item.NewsId);
map(dbNews, item);
_table.Context.SubmitChanges();
}
}
L2S supports neither layer supertypes nor using interface members in queries, which makes reuse quite difficult. One option is to dynamically build an expression tree. It's a bit messy, but if you isolate it to your base class repository it's not that bad.
Here is an example:
public interface IEntity
{
int Id { get; }
}
public partial class News : IEntity
{
}
public class Repository<T> where T : class, IEntity
{
private readonly DataContext _db;
public Repository(DataContext db)
{
_db = db;
}
public T Get(int id)
{
Expression<Func<T, bool>> hasId = HasId(id);
return _db.GetTable<T>().Single(hasId);
}
// entity => entity.Id == id;
private Expression<Func<T, bool>> HasId(int id)
{
ParameterExpression entityParameter = Expression.Parameter(typeof (T), "entity");
return Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(entityParameter, "Id"),
Expression.Constant(id)
),
new[] {entityParameter}
);
}
}
See also http://msdn.microsoft.com/en-us/library/bb397951.aspx
It really helps to have a layer supertype for entities. They will share an Id property. You won't have to deal with an expression to represent the id proeprty, you'll just know what it is.
The template method pattern. In this pattern your base Update does all the work calling helper methods in order, and your derived classes implement those protected abstract helper methods.
Related
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'm working on a repository for a list of entities, and I should repeat thea same class more than once, the only difference is type type .. is there a way to make it generic?
It should quite easy, for sure I don't know how to make this generic:
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
The class I'm repeating it this:
public class UserProfileRepository : IEntityRepository<IUserProfile>
{
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
public IUserProfile[] GetAll()
{
return _rep.GetAll();
}
public IUserProfile GetById(int id)
{
return _rep.GetById(id);
}
public IQueryable<IUserProfile> Query(Expression<Func<IUserProfile, bool>> filter)
{
return _rep.Query(filter);
}
}
#NickBray hit the nail on the head. Regardless of how different or similar the actual concrete repository implementations are the DAL class in your example should expose the repository instance via an interface.
Ideally the exposed interface would be declared something like this.
interface IUserProfileRepository : IEntityRepository<IUserProfile>
{
}
This way you could add custom IUserProfile methods as necessary. While the IEntityRepository interface would define the common methods Add, Update, Remove and various QueryXXX methods.
I hope this example helpful for you. If I correctly understood your question, you want to make generizable your repository based on the interface "IEntityRepository".
Try something like this:
public class UserProfileRepository<TUserProfile> : IEntityRepository<TUserProfile> where TUserProfile : IUserProfile
{
private Namespace.DAL.UserProfileRepository _rep = new Namespace.DAL.UserProfileRepository();
public TUserProfile[] GetAll()
{
return _rep.GetAll();
}
public TUserProfile GetById(int id)
{
return _rep.GetById(id);
}
public IQueryable<TUserProfile> Query(Expression<Func<TUserProfile, bool>> filter)
{
return _rep.Query(filter);
}
}
I have the following DBML modification (i'm using Linq to SQL as a DAL).
public interface ILinqSQLObject { }
// these are objects from SQL Server mapped into Linq to SQL
public partial class NEWDEBT : ILinqSQLObject { }
public partial class OLDDEBT : ILinqSQLObject { }
public partial class VIPDEBT : ILinqSQLObject { }
With that i can manipulate my Linq objects more properly on other areas.
I've just done an IRepository pattern implementation.
public interface IDebtManager<T>
{
IQueryable<T> GetAllDebts();
IQueryable T GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate);
void Insert(T debt);
// other methods
}
public class DebtManager<T> : IDebtManager<T> where T : class, ILinqSQLObject
{
DebtContext conn = new DebtContext();
protected System.Data.Linq.Table<T> table;
public DebtManager()
{
table = conn.GetTable<T>();
}
public void Insert(T debt)
{
throw new NotImplementedException();
}
public IQueryable<T> GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return table.Where(predicate);
}
public IQueryable<T> GetAllDebts()
{
return table;
}
}
And that works flawlessly. But, there are sometimes that i don't know, on compilation time, which specific table i'll be using. For that i tried to create a simple generic factory for my DebtManager.
public static class DebtFactoryManager
{
public static DebtManager<ILinqSQLObject> GetDebtManager(string debtType)
{
switch (debtType)
{
case "New Client":
return new DebtManager<NEWDEBT>();
case "Old Client":
return new DebtManager<OLDDEBT>();
case "VIP Client":
return new DebtManager<VIPDEBT>();
default:
return new DebtManager<NEWDEBT>();
}
return null;
}
}
However it doesn't work. It says that i cannot 'implicity convert DebtManager<NEWDEBT> to DebtManager<ILinqSQLObject>', but if NEWDEBT implements ILinqSQLObject, why isn't the compiler recognizing it? Obviously i'm doing some mistake but i can't see it.
This error is caused by the fact that generics do not implicitly support covariance; that is, treating a specific generic parameter type as if it were one of its base types.
Couple ways around this. First, you can define a non-generic DebtManager base class that the generic DebtManager inherits from, and return that. Second, you can define a generic interface that DebtManager implements; generic interfaces CAN be defined to be covariant, by using the keyword out before the generic type parameter.
EDIT: Let's go back to the primary need. You may not know, at compile-time, what type of object you will be required to work with and therefore you don't know which Repository you need. Might I suggest, then, that instead of a Repository-per-table architecture, you use a Repository-per-database. DebtManager is already generic to any Linq to SQL type; why not then make the methods generic as well, allowing them to be generic from call to call?
public interface IRepository<T> where T:class, ILinqSqlObject
{
IQueryable<TSpec> GetAllDebts<TSpec>() where TSpec : T;
IQueryable<TSpec> GetSpecificDebt<TSpec>(System.Linq.Expressions.Expression<Func<TSpec, bool>> predicate) where TSpec : T;
void Insert<TSpec>(TSpec debt) where TSpec:T;
// other methods
}
interface IDebtObject : ILinqSqlObject
public interface IDebtManager:IRepository<IDebtObject> { }
public class DebtManager:IDebtManager
{
DebtContext conn = new DebtContext();
public DebtManager()
{
}
public void Insert<T>(T debt) where T:IDebtObject
{
throw new NotImplementedException();
}
public IQueryable<T> GetSpecificDebt(System.Linq.Expressions.Expression<Func<T, bool>> predicate) where T:IDebtObject
{
return conn.GetTable<T>().Where(predicate);
}
public IQueryable<T> GetAllDebts<T>() where T:IDebtObject
{
return conn.GetTable<T>();
}
}
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.