Should I define a repository for each entity - entity-framework

I have been learning about MVC and I am using Entity Framework. What I am trying to understand is repositories. Every tutorial I've read deals with one entity and at that level I have a understanding, but what about multiple tables. I use a variation of code-first, where I associate my model classes with an existing database. In my database,there are three tables; User, Journey and UserJourney (linked table). User and Journey have a many-to-many relationship. Should I have a repository for each entity? Has aggregates any use here? In the long run I want to query the database to find user's journeys and pass to a view.
My question is perhaps vague, but I am quite confused on this matter, so any help in understanding this would be appreciated!

Normally repositories should not be defined for each entity but rather per aggregate root. You have entities that cannot live by themselves, but are related to some parent entity. This parent entity is called aggregate root and you should have a repository for each of them.

Search for a concept called GenericRepository. It will help in getting rid of the repository for each entity problem. Sample below:
public interface IGenericRepository<T> where T : class
{
IEnumerable<T> GetAll();
T SingleOrDefault(Expression<Func<T, bool>> predicate);
IEnumerable<T> Get(Expression<Func<T, bool>> predicate);
void Insert(T entity);
void Update(T entity);
void Delete(object id);
void Delete(T entity);
}
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
readonly MyDbContext _context;
readonly DbSet<T> _dbSet;
public GenericRepository(PfsDbContext context)
{
_context = context;
_dbSet = context.Set<T>();
}
public virtual IEnumerable<T> GetAll()
{
return _dbSet.AsEnumerable();
}
public T SingleOrDefault(Expression<Func<T, bool>> predicate)
{
return _dbSet.Where(predicate).SingleOrDefault();
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
{
return _dbSet.Where(predicate);
}
public void Insert(T entity)
{
_dbSet.Add(entity);
}
public void Update(T entityToUpdate)
{
_dbSet.Attach(entityToUpdate);
_context.Entry(entityToUpdate).State = EntityState.Modified;
}
public void Delete(T entity)
{
if (_context.Entry(entity).State == EntityState.Detached)
{
_dbSet.Attach(entity);
}
_dbSet.Remove(entity);
}
public void Delete(object id)
{
var entityToDelete = _dbSet.Find(id);
Delete(entityToDelete);
}
}
You can then use it as
var userRepository = new GenericRepository<User>(_context);
var journeyRepository = new GenericRepository<Journey>(_context);

Related

Modern ORM vs Repository/IoW pattern

I read a lots of content about the usage of Entity Framework/NHibernate (or basically any other modern ORM) with the repository/UnitOfWork patterns. Apparently the community is divided. Some would say the repository pattern is almost mandatory, some others would say that it's a waste of time...
Well, I come up with my "own" design and I just wanted to share it with you in order to get some feedback...
In the past, my company decided to develop and use it's own ORM. It's now a total disaster. Performance, stability (and basically everything else) are terrible. We want to switch to another ORM and we want to be keep the ability to switch from an ORM to another. Indeed, we are now using Sharepoint 2010. It means 3.5 and thus NHibernate 3.4 and Entity Framework 4. We plan to migrate to SharePoint 2013 ASAP in order to be able to rely on .net 4.5/EF 6.1/... So we will have to switch to another ORM pretty soon.
To do so, I have developed a set of classes implementing the "IDatabaseContext" interface.
public interface IDatabaseContext : IDisposable
{
IQueryable<TEntity> AsQueryable<TEntity>()
where TEntity : EntityBase;
IList<TEntity> AsList<TEntity>()
where TEntity : EntityBase;
IList<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate)
where TEntity : EntityBase;
long Count<TEntity>()
where TEntity : EntityBase;
void Add<TEntity>(TEntity entity)
where TEntity : EntityBase;
void Delete<TEntity>(TEntity entity)
where TEntity : EntityBase;
void Update<TEntity>(TEntity entity)
where TEntity : EntityBase;
}
For example, for the prototype I have decided to use NHibernate:
public class NHibernateDbContext : IDatabaseContext
{
private ISession _session = null;
public NHibernateDbContext(ISessionFactory factory)
{
if (factory == null)
throw new ArgumentNullException("factory");
_session = factory.OpenSession();
}
public IQueryable<TEntity> AsQueryable<TEntity>()
where TEntity : EntityBase
{
return _session.Query<TEntity>();
}
public IList<TEntity> AsList<TEntity>()
where TEntity : EntityBase
{
return _session.QueryOver<TEntity>()
.List<TEntity>();
}
public IList<TEntity> Find<TEntity>(Expression<Func<TEntity, bool>> predicate)
where TEntity : EntityBase
{
...
}
public long Count<TEntity>()
where TEntity : EntityBase
{
return _session.QueryOver<TEntity>()
.RowCountInt64();
}
public void Add<TEntity>(TEntity entity)
where TEntity : EntityBase
{
if (entity == null)
throw new ArgumentNullException("entity");
UseTransaction(() => _session.Save(entity));
}
public void Delete<TEntity>(TEntity entity)
where TEntity : EntityBase
{
...
}
public void Update<TEntity>(TEntity entity)
where TEntity : EntityBase
{
...
}
private void UseTransaction(Action action)
{
using (var transaction = _session.BeginTransaction())
{
try
{
action();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
}
public void Dispose()
{
if (_session != null)
_session.Dispose();
}
}
Eventually, my service layer (each entity are associated with a service) relies on this interface so I don't introduce a dependency over the ORM technology.
public class CountryService<Country> : IService<Country>
where Country : EntityBase
{
private IDatabaseContext _context;
public GenericService(IDatabaseContext context)
{
if (context == null)
throw new ArgumentNullException("context");
_context = context;
}
public IList<Country> GetAll()
{
return _context.AsList<Country>();
}
public IList<Country> Find(Expression<Func<Country, bool>> predicate)
{
return _context.Find(predicate);
}
...
}
Eventually, to call a method from the service layer, you just need two lines of code:
var service = new CountryService(new NHibernateDbContext(...)));
or
var service = new CountryService(new TestDbContext(...)));
...
I find this architecture quite simple and very convenient to use. I didn't find (yet) any drawback/flaws/errors.
So what do you think? Did I miss something big? Is there something I can improve?
Thank you for all your feedback...
Regards,
Sebastien
Personally i think your approach is solid. But equally Im surprised you see this approach as very different to the repository / Unit of Work Pattern.
Your IService layer is directly comparable to a basic Unit of Work layer combined with a repository layer implemented via an interface. The repository layer should implement an Interface and be injected or discovered by a core layer to avoid dependency on the underlying ORM.
The actual implementation of your Repository and Unit of Work layers would be specific to the underlying ORM. But you could replace a RepositoryEF class with RespositoryNH or vice versa.
If done properly and used with dependency injection, the Core application never knows what the ORM is.
The problem is with SOME peoples Repository Patterns, they leak the underlying orm by allowing code that accesses ORM directly or leaks the ORMs structures.
eg if an IREPOSITORY exposed DBSet or Context from Entity Framework, then the whole app can be locked to EF.
eg Unit Of Work Interface
public interface ILuw {
IRepositoryBase<TPoco> GetRepository<TPoco>() where TPoco : BaseObject, new();
void Commit(OperationResult operationResult=null, bool silent=false);
}
and a IRepositoryBase interface
public interface IRepositoryBase<TPoco> : IRepositoryCheck<TPoco> where TPoco : BaseObject,new() {
void ShortDump();
object OriginalPropertyValue(TPoco poco, string propertyName);
IList<ObjectPair> GetChanges(object poco, string singlePropName=null);
IQueryable<TPoco> AllQ();
bool Any(Expression<Func<TPoco, bool>> predicate);
int Count();
IQueryable<TPoco> GetListQ(Expression<Func<TPoco, bool>> predicate);
IList<TPoco> GetList(Expression<Func<TPoco, bool>> predicate);
IList<TPoco> GetListOfIds(List<string>ids );
IOrderedQueryable<TPoco> GetSortedList<TSortKey>(Expression<Func<TPoco, bool>> predicate,
Expression<Func<TPoco, TSortKey>> sortBy, bool descending);
IQueryable<TPoco> GetSortedPageList<TSortKey>(Expression<Func<TPoco, bool>> predicate,
Expression<Func<TPoco, TSortKey>> sortByPropertyName,
bool descending,
int skipRecords,
int takeRecords);
TPoco Find(params object[] keyValues);
TPoco Find(string id); // single key in string format, must eb converted to underlying type first.
int DeleteWhere(Expression<Func<TPoco, bool>> predicate);
bool Delete(params object[] keyValues);
TPoco Get(Expression<Func<TPoco, bool>> predicate);
TPoco GetLocalThenDb(Expression<Func<TPoco, bool>> predicate);
IList<TPoco> GetListLocalThenDb(Expression<Func<TPoco, bool>> predicate);
TU GetProjection<TU>(Expression<Func<TPoco, bool>> predicate, Expression<Func<TPoco, TU>> columns);
/// <summary>
/// To use the projection enter an anonymous type like s => new { s.Id , s.UserName});
/// </summary>
IList<TU> GetProjectionList<TU>(Expression<Func<TPoco, bool>> predicate, Expression<Func<TPoco, TU>> columns);
bool Add(object poco,bool withCheck=true);
bool Remove(object poco);
bool Change(object poco, bool withCheck=true);
bool AddOrUpdate(TPoco poco, bool withCheck = true);
}
Your approach is sound, but there are few considerations
AsList<TEntity>() method is a recipe for abuse, many new developers might user this method to get list of data and will probably do the filtering in memory
How transactions are handled.
Personally I'd go with the repository pattern phil soady suggested, but I would not use that much of methods in the IRepository interface.
public interface IRepository<T> where T:IEntity
{
T Single(long id);
T Save(T entity);
void Delete(T entity);
IQueryable<T> FilterBy(Expression<Func<T, bool>> expression);
}
And when the type specific query is required it's handled in it's own repository, like
public interface IContactRepository : IRepository<Contact>
{
IList<Contact> GetForUser(int userId);
}
And handling of transactions, I would go for Using the unit of work per request pattern where you don't have to manually handle transaction each and every time database is updated. A global ActionFilter would be enough to achieve this.

EF Code First check for property in generic repository

In my project, I'm using EF Code First approach following Code Camper structure. So i have generic repository IRepository;
public interface IRepository<T> where T : class
{
IQueryable<T> GetAll();
T GetById(int id);
void Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(int id);
}
and then it's implementation EFRepository<T>
public class EFRepository<T> : IRepository<T> where T : class
{
public EFRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
protected DbContext DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public virtual IQueryable<T> GetAll()
{
return DbSet;
}
public virtual T GetById(int id)
{
//return DbSet.FirstOrDefault(PredicateBuilder.GetByIdPredicate<T>(id));
return DbSet.Find(id);
}
public virtual void Add(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Detached)
{
dbEntityEntry.State = EntityState.Added;
}
else
{
DbSet.Add(entity);
}
}
public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State == EntityState.Detached)
{
DbSet.Attach(entity);
}
dbEntityEntry.State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Deleted)
{
dbEntityEntry.State = EntityState.Deleted;
}
else
{
DbSet.Attach(entity);
DbSet.Remove(entity);
}
}
public virtual void Delete(int id)
{
var entity = GetById(id);
if (entity == null) return; // not found; assume already deleted.
Delete(entity);
}
}
Based on customer needs, i should not delete any DB records, so for most(not all of them) tables I have isDeleted property to mark record as deleted. And these records which marked as isDeleted should not appear to users
My question is: How in my generic repository implementation check for that isDeleted property while I'm expecting generic object T.
For example GetAll function should be:
public virtual IQueryable<T> GetAll()
{
return DbSet.where(x=>x.isDelete == false);
}
Any ideas, how i can do that?
Create an interface with IsDeleted property and inherit all your models from it. Then you could modify your repository like this:
public class EFRepository<T> : IRepository<T> where T : TypeOfYourNewInterface
Now you can access IsDeleted in generic methods.
I could not find a suitable solution to my problem. After more searching i ended with 3 solutions:
Create extension methods.
Create a custom IDbSet which can accept a filter expression.
Add a discriminator to every model.
I choosed solution(3) although, I don't like it much

autofac registergeneric error "sequence contains no element"

Using Autofac, I tried to use my generic type :
public interface IRepository<T> where T : class
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
void Delete(Expression<Func<T, bool>> where);
T GetById(long Id);
T GetById(string Id);
T Get(Expression<Func<T, bool>> where);
IEnumerable<T> GetAll();
IEnumerable<T> GetMany(Expression<Func<T, bool>> where);
}
to register my generic class :
public abstract class RepositoryBase<T> where T : class
{
private iMOSSContainer dataContext;
private readonly IDbSet<T> dbset;
protected RepositoryBase()
{
DatabaseFactory = new DatabaseFactory();
dbset = DataContext.Set<T>();
}
protected RepositoryBase(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected iMOSSContainer DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
public virtual void Add(T entity)
{
dbset.Add(entity);
}
public virtual void Update(T entity)
{
dbset.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
dbset.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = dbset.Where<T>(where).AsEnumerable();
foreach (T obj in objects)
dbset.Remove(obj);
}
public virtual T GetById(long id)
{
return dbset.Find(id);
}
public virtual T GetById(string id)
{
return dbset.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return dbset.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return dbset.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return dbset.Where(where).FirstOrDefault<T>();
}
}
this way :
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(RepositoryBase<>)).As(typeof(IRepository<>)); //.InstancePerLifetimeScope();
Container = builder.Build();
And returns an error "sequence contains no element" when building a container.
Did i do something wrong with the code? I already tried to search for an answer to no avail. So, your help would be pretty much appreciated.
Ok, then i changed the RepositoryBase class like this :
public class RepositoryBase<T> : IRepository<T> where T : class
{
private iMOSSContainer dataContext;
private readonly IDbSet<T> dbset;
public RepositoryBase()
{
DatabaseFactory = new DatabaseFactory();
dbset = DataContext.Set<T>();
}
So :
i use the "iRepository" interface (and move the "where T : class"
statement at the end of the line)
i remove the "abstract" class (because it leads to another error)
set the default constructor to "public" (because it leads to another
error, as well)
And everything is working good right now.
Your RepositoryBase type is abstract, therefore it can't be registered. You need to register non-abstract types. I'm guessing what you're intending to do is register all subtypes of RepositoryBase.

UnitOfWork and Entity Framework Contexts

So the problem I am trying to solve is this; We are using Entity Framework to access our Oracle database that has 1200-1500 tables. Now mind you we are not accessing them all, but possibly could have 800+ to access. We are using the UnitOfWork --> Repository --> Service pattern and that works great, but we are trying to figure out if we should have one big DbContext, or multiple little contexts that are specific to the task at hand.
Our UnitOfWork is setup using an EFUnitOfWorkBase like so:
public abstract class EFUnitOfWorkBase : IUnitOfWork
{
private bool isDisposed = false;
public DbContextBase Context { get; set; }
protected EFUnitOfWorkBase(DbContextBase context)
{
Context = context;
}
public int Commit()
{
return Context.SaveChanges();
}
public void Dispose()
{
if (!isDisposed)
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
isDisposed = true;
if (disposing)
{
if (this.Context != null)
this.Context.Dispose();
}
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : Common.EntityBase<TEntity>
{
return new Repository<TEntity>(this);
}
}
Any unit of work we create extends that base one and provides the context like so:
public class EmployeeDirectoryUnitOfWork : EFUnitOfWorkBase
{
public EmployeeDirectoryUnitOfWork(string connectionString)
: base(new EmployeeDirectoryContext(connectionString))
{
}
}
The DbContext is passed a connection string through the unit of work.
The Repository looks like this:
public abstract class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
protected DbContextBase Context;
protected DbSet<TEntity> EntitySet;
public RepositoryBase(EFUnitOfWorkBase unitOfWork)
{
Enforce.ArgumentNotNull(unitOfWork, "unitOfWork");
Context = unitOfWork.Context;
EntitySet = Context.Set<TEntity>();
}
public TEntity Add(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Add(entity);
}
public TEntity Attach(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Attach(entity);
}
public TEntity Delete(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
return EntitySet.Remove(entity);
}
public System.Linq.IQueryable<TEntity> Query()
{
return EntitySet.AsQueryable();
}
public TEntity Save(TEntity entity)
{
Enforce.ArgumentNotNull(entity, "entity");
Attach(entity);
Context.MarkModified(entity);
return entity;
}
}
Any suggestions on how to best handle this situation?
In such a case when you have a large application like this, I think you should probably go for a more Domain Driven Design approach and split the contexts into some separate, bounded contexts. This way when later developers are adding features to the program they will be confined to only being able to access certain tables depending on which context they will be using there.
For better information, Julie Lerman recently came out with a course on Pluralsight about Entity Framework in the Enterprise that's really good. She posted a small clip of it (actually about bounded contexts) on this site. It's a very good course, and I highly recommend it, especially for what you appear to be doing.

Is the Entity Framework 4 "Unit of Work" pattern the way to go for generic repositories?

I am looking into creating an Entity Framework 4 generic repository for a new ASP.NET MVC project i am working on. I have been looking at various tutorials and they all seem to use the Unit of Work pattern ...
From what i have been reading, EF is using this already within the ObjectContext and you are simply extending this to make your own Units of Work.
Source: http://dotnet.dzone.com/news/using-unit-work-pattern-entity?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+zones%2Fdotnet+(.NET+Zone)
Why would one go to the effort of doing this?
Is this the preferred way of working with generic repositories?
Many thanks,
Kohan.
This is not the way I would work with generic repositories. First of all, I would share ObjectContext between ClassARepository, CalssBRepository and other repositories in current request. Using IOC container, using injection and per request behavior is recommended:
This is how my generic repositories look like:
public interface IRepository<T>
{
//Retrieves list of items in table
IQueryable<T> List();
IQueryable<T> List(params string[] includes);
//Creates from detached item
void Create(T item);
void Delete(int id);
T Get(int id);
T Get(int id, params string[] includes);
void SaveChanges();
}
public class Repository<T> : IRepository<T> where T : EntityObject
{
private ObjectContext _ctx;
public Repository(ObjectContext ctx)
{
_ctx = ctx;
}
private static string EntitySetName
{
get
{
return String.Format(#"{0}Set", typeof(T).Name);
}
}
private ObjectQuery<T> ObjectQueryList()
{
var list = _ctx.CreateQuery<T>(EntitySetName);
return list;
}
#region IRepository<T> Members
public IQueryable<T> List()
{
return ObjectQueryList().OrderBy(#"it.ID").AsQueryable();
}
public IQueryable<T> List(params string[] includes)
{
var list = ObjectQueryList();
foreach(string include in includes)
{
list = list.Include(include);
}
return list;
}
public void Create(T item)
{
_ctx.AddObject(EntitySetName, item);
}
public void Delete(int id)
{
var item = Get(id);
_ctx.DeleteObject(item);
}
public T Get(int id)
{
var list = ObjectQueryList();
return list.Where("ID = #0", id).First();
}
public T Get(int id, params string[] includes)
{
var list = List(includes);
return list.Where("ID = #0", id).First();
}
public void SaveChanges()
{
_ctx.SaveChanges();
}
#endregion
}
ObjectContext is injected through constructor. List() methods return IQueryable for further processing in business layer (service) objects. Service layer returns List or IEnumerable, so there is no deferred execution in views.
This code was created using EF1. EF4 version can be a little different and simpler.