A Generic CRUD Repository for Entity Framework
I wrote a post a while ago about using Generics for lookup tables in Entity Framework and I suggested that the idea could be extended to include all objects and CRUD operations.
Well, I’ve put together a generic Repository that can be used in your project to give you a consistent base class for all your repositories. It’s quite long, so sorry about that.
This implementation follows our SSW Rule, Do you use the repository pattern for data access.
public class DataRepository<TContext> : IDataRepository<TContext> where TContext : ObjectContext
{
// Cached ObjectSets so changes persist
protected Dictionary<string, object> CachedObjects = new Dictionary<string, object>();
protected ObjectSet<TEntity> GetObjectSet<TEntity>() where TEntity : EntityObject
{
var fulltypename = typeof (TEntity).AssemblyQualifiedName;
if (fulltypename == null)
throw new ArgumentException("Invalid Type passed to GetObjectSet!");
if (!CachedObjects.ContainsKey(fulltypename))
{
var objectset = _context.CreateObjectSet<TEntity>();
CachedObjects.Add(fulltypename, objectset);
}
return CachedObjects[fulltypename] as ObjectSet<TEntity>;
}
protected TContext _context;
/// <summary>
/// Constructor that takes a context
/// </summary>
/// <param name="context">An established data context</param>
public DataRepository(TContext context)
{
_context = context;
}
/// <summary>
/// Constructor that takes a connection string and an EDMX name
/// </summary>
/// <param name="connectionString">The connection string</param>
/// <param name="edmxName">The name of the EDMX so we can build an Entity Connection string</param>
public DataRepository(string connectionString, string edmxName)
{
var entityConnection =
String.Format(
"metadata=res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl;provider=System.Data.SqlClient;provider connection string=",
edmxName);
// append the database connection string and save
entityConnection = entityConnection + "\"" + connectionString + "\"";
var targetType = typeof (TContext);
var ctx = Activator.CreateInstance(targetType, entityConnection);
_context = (TContext) ctx;
}
public IQueryable<TEntity> Fetch<TEntity>() where TEntity : EntityObject
{
return GetObjectSet<TEntity>();
}
public IEnumerable<TEntity> GetAll<TEntity>() where TEntity : EntityObject
{
return GetObjectSet<TEntity>().AsEnumerable();
}
public IEnumerable<TEntity> Find<TEntity>(Func<TEntity, bool> predicate) where TEntity : EntityObject
{
return GetObjectSet<TEntity>().Where(predicate);
}
public TEntity GetSingle<TEntity>(Func<TEntity, bool> predicate) where TEntity : EntityObject
{
return GetObjectSet<TEntity>().Single(predicate);
}
public TEntity GetFirst<TEntity>(Func<TEntity, bool> predicate) where TEntity : EntityObject
{
return GetObjectSet<TEntity>().First(predicate);
}
public IEnumerable<TEntity> GetLookup<TEntity>() where TEntity : EntityObject
{
return GetObjectSet<TEntity>().ToList();
}
public void Add<TEntity>(TEntity entity) where TEntity : EntityObject
{
if (entity == null)
throw new ArgumentException("Cannot add a null entity");
GetObjectSet<TEntity>().AddObject(entity);
}
public void Delete<TEntity>(TEntity entity) where TEntity : EntityObject
{
if (entity == null)
throw new ArgumentException("Cannot delete a null entity");
GetObjectSet<TEntity>().DeleteObject(entity);
}
public void Attach<TEntity>(TEntity entity) where TEntity : EntityObject
{
if (entity == null)
throw new ArgumentException("Cannot attach a null entity");
GetObjectSet<TEntity>().Attach(entity);
}
public void SaveChanges()
{
SaveChanges(SaveOptions.None);
}
public void SaveChanges(SaveOptions options)
{
_context.SaveChanges(options);
}
public void Refresh<TEntity>(TEntity entity) where TEntity : EntityObject
{
_context.Refresh(RefreshMode.StoreWins, entity);
}
public void Refresh<TEntity>(IEnumerable<TEntity> entities) where TEntity : EntityObject
{
_context.Refresh(RefreshMode.StoreWins, entities);
}
#region IDisposable implementation
private bool disposedValue;
protected void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
// dispose managed state here if required
}
// dispose unmanaged objects and set large fields to null
}
this.disposedValue = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
A lot of code to be sure, but you only need one of these. After that, whenever you create a new EDMX, you can create a Repository that inherits from this base repository.
Let’s look at using it for the same AdventureWorks repository I used last time:
Here’s how you might implement a repository for this data model:
public class AdventureWorksRepository : DataRepository
{
public AdventureWorksRepository(string connectionString) : base(connectionString, "AdventureWorksEntities") { }
}
Yep, seriously. That’s it. Now you have access to all your common CRUD operations (as well as Linq queries) and can do things like this:
var repository = new AdventureWorksRepository(MyConnectionString);
// return all states and provinces
var states = repository.GetAll<StateProvince>();
// get states and provinces with a three letter code
var threeLetterStates = repository.Fetch<StateProvince>()
.Where(s => s.StateProvinceCode.Length == 3)
// get a customer
var cust = repository.GetSingle<Customer>(c => c.CustomerID == 1);
// delete that customer
repository.Delete(cust);
// get a contact
var contact = repository.GetSingle<Contact>(c => c.ContactID == 1);
// edit some properties
contact.Title = "Mr";
contact.Phone = "61 411 111 111";
// save all the changes (this will save the customer deletion and the updated contact)
repository.SaveChanges();
So just by inheriting a base repository class, you can get some really powerful behaviour which is specific to your data model.
I’d be interested to hear your thoughts on this technique, particularly if you try it in your own project.

[...] “Down the track” has arrived, and I now have an extension to this post that shows a single generic repository that you can use across your [...]
I find when I’m using the Entity Framework it is a good idea to keep in mind the dual nature of the “Context” object (either the ObjectContext or DbContext).
They are a combination of the “Unit of Work” container, for tracking changes and committing them at once, and the “Repository” for data access. So with this in mind I usually split them out.
First I copy the unit of work type methods into an interface:
public interface IUnitOfWork : IDisposable { void AcceptAllChanges(); void DetectChanges(); int SaveChanges(); int SaveChanges(bool acceptChangesDuringSave); virtual int SaveChanges(SaveOptions options); }We apply the “IUnitOfWork” interface to our ObjectContext and use it to save our changes.
Then we create a base repository with interface (much like your’s, Damian) which accepts the very same ObjectContext object and exposes methods of a particular entity:
(the comments sanitizer eats angle brackets so I’ll use pipe | instead)
*Note: Fixed*
public interface IBaseRepository<TEntity> where TEntity : class, IEntity { TEntity Create(); void Add(TEntity entity); void Delete(TEntity entity); IQueryable<TEntity> GetAll(); TEntity GetById(int id); } public abstract class BaseRepository<TContext, TEntity> : IBaseRepository<TEntity> where TContext : ObjectContext where TEntity : class, IEntity { private TContext _context; protected TContext Context { get { return _context; } } public BaseRepository(TContext context) { _context = context; } public void Add(TEntity entity) { Context.CreateObjectSet<TEntity>().AddObject(entity); } public IQueryable<TEntity> GetAll() { return Context.CreateObjectSet<TEntity>().AsQueryable<TEntity>(); } public void Delete(TEntity entity) { Context.CreateObjectSet<TEntity>().DeleteObject(entity); } public TEntity Create() { return Context.CreateObjectSet<TEntity>().CreateObject(); } public TEntity GetById(int id) { return Context.CreateObjectSet<TEntity>().SingleOrDefault(e => e.Id == id); } }How do we use this? Quite simply:
public interface IContactRepository : IBaseRepository<Contact> { } public class IContactRepository<MyContext, Contact> : IBaseRepository<Contact> { public ContactRepository(MyContext context) : base(context) { } }If we have specific searches we wish to perform only on “Contact” objects we can add a method to our IContactRepository interface then implement it on the class and we are all set.
That’s it. Since we have all the interfaces unit testing becomes a breeze and I usually use an IoC container to automatically wire everything together.
That does look like a pretty good method. I particularly like how you’ve separated the UnitOfWork behaviour.
I had left out the interface for a bit more conciseness in my example, but it definitely makes sense to use one for testability and IoC.
My original implementation of this was bound to a single entity (as yours is), but we found we needed more than just operations on one entity. For example if our screen is for editing a Contact, we would also want lookups for States and Contact Types, and the ability to add Addresses and phone numbers. We were ending up with quite a few independent repositories.
By combining them, we found it was more efficient. Yes, it’s moving away somewhat from a “repository” pattern, but we didn’t need 10 repositories for a 10-object data model. We had a repository of sorts which could handle all objects in our model.
That said, I’m aware that using your method you can use the same context for each of the repositories, and the separation of that context from the actual CRUD operations facilitates this nicely.
Thanks, I’ll definitely take the Unit of Work separation on board, and I’ll think again about isolating the objects into their own repositories.
Hi Damian! i am beginner in Entity framework, can u give the complete sample, as in your blog u didnt give implementation of IDataRespository i know it is an interface and abstract methods which are in DataRepository class. but i need that interface.
And please also tell me how can i make 3 layer architecture with entity framework.
Thanks in advance
Hi Nasir,
The IDataRepository is just an interface that defines all the methods in my example DataRepository. The easiest way to create it is just to copy and paste all the method definitions (removing public/private obviously).
As for the 3 layer architecture, the Repository is really just part of one layer that handles your data access. By calling custom methods on your concrete repository (e.g. AdventureWorksRepository) or just using the generic methods, you’re really calling into a Data Access Layer. The entities themselves act as models you can pass around your layers. Above that, it’s really your choice. You might want a Business Layer that makes calls to your repository for data, but handles your business rules and security. Above that, your UI layer is likely to call methods in the Business Layer.
Thanks for the article. My friend.
[...] You may be familiar with my previous posts describing the implementation of design patterns for Entity Framework. It started with using generics for lookup tables, and followed with a generic CRUD repository. [...]
[...] Damian Brady’s Blog http://blog.damianbrady.com.au/2012/03/07/a-generic-crud-repository-for-entity-framework/ [...]
Adrian – I love your example, but would you be able to post the usage of the IUnitOfWork? I understand the BaseRepository, but I don’t quite understand how the unit of work interface connects to the BaseRepository you’ve shown.
thanks!
Hi Damian. How to dbcontext repository? Please help me.
Hi there,
Do you see any advantage (performance or other wise) of your method:
GetObjectSet().DeleteObject(entity);
Over this:
this.Entry(entity).State = System.Data.EntityState.Deleted;
Just interested to know, it may even be doing the same thing internally
Thanks
Rick
Hi,
Do you have any example of how to implement this for the beginners? Your example of ‘how to use’ does not work.
Thanks.
Hi Anup,
Can you be a bit more specific? What’s going wrong? The “how to use” example is very basic, but it should work.
Damian
Hi Damian,
Thanks for the reply.
I managed to get it worked. Could you please show me an example of the below,
Lets say, I have three tables. Emp Dept and job. A dept can have many emp and an emp can do more than one job. How can I retrieve job details for all employees work in dept 1.