Generic Repository for Entity Framework

*UPDATED 9/6/2012*
Thanks to Stephen Dooley for bringing to my attention that Mikael’s post is no longer available.  I have updated the post to include the extension methods that he had originally posted.  You can find them at the end of the post.
*End Update*

I have started trying to learn how to leverage the Entity Framework for a the re-write of the GiveCamp Starter Site and wanted to implement a generic repository for data access like I use on most of my projects.  I started with the example given by Mikael Henriksson’s Post Generic Repository for Entity Framework for Pluralized Entity Set.  I modified it to fit my standard Repository interface and took the liberty of simplifying it in a few places.

I have run this through several test and haven’t found any issues. I would love those with a critical eye to give this a look over and let me know if I am missing anything.

The IRepository Interface

 1: public interface IRepository : IDisposable
 2:    {
 3:      T Get<T>(int id) where T : IEntityWithKey;
 4:      T Get<T>(Expression<Func<T, bool>> predicate) where T : IEntityWithKey;
 5:        IQueryable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : IEntityWithKey; 
 6:      T Save<T>(T entity) where T : IEntityWithKey;
 7:      T Delete<T>(T entity) where T : IEntityWithKey;
 8:    }

I did use the ObjectContextExtensions from Mikael’s post because they did such a good job of solving the issue of getting the EntitySetName. I am not going go into a lot of detail explaining what is going on because a feel the class pretty much explains itself.

The Repository Class:

 1: public class EntityFrameworkRepository : IRepository   
 2: {
 3:     private readonly ObjectContext context;
 4:     public EntityFrameworkRepository()
 5:     {
 6:         context = new WmdDemoEntities();
 7:     }
 8:      
 9:     public EntityFrameworkRepository(ObjectContext entityContext)
 10:     {
 11:         context = entityContext;
 12:     }
 13:     
 14:     public T Get<T>(int id) where T : IEntityWithKey
 15:     {
 16:         IEnumerable<KeyValuePair<string, object>> entityKeyValues = new[] { new KeyValuePair<string, object>("Id", id) };
 17:         var key = new EntityKey(context.GetEntitySet<T>().Name, entityKeyValues);
 18:         return (T)context.GetObjectByKey(key);
 19:     }
 20:     
 21:     public T Get<T>(Expression<Func<T, bool>> predicate) where T : IEntityWithKey
 22:     {
 23:         return context.CreateQuery<T>("[" + context.GetEntitySet<T>().Name + "]")
 24:         .Where(predicate)
 25:         .FirstOrDefault();
 26:     }
 27:     
 28:     public IQueryable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : IEntityWithKey
 29:     {
 30:         return context
 31:         .CreateQuery<T>("[" + context.GetEntitySet<T>().Name + "]")
 32:         .Where(predicate);
 33:     }
 34:      
 35:     public T Save<T>(T entity) where T : IEntityWithKey
 36:     {
 37:         object originalItem;
 38:            if (context.TryGetObjectByKey(entity.EntityKey, out originalItem))
 39:             context.ApplyPropertyChanges(entity.EntityKey.EntitySetName, entity); 
 40:         else
 41:             context.AddObject(entity.EntityKey.EntitySetName, entity);
 42:        
 43:        context.SaveChanges();
 44:        return entity;
 45:     }
 46:     
 47:     public T Delete<T>(T entity) where T : IEntityWithKey
 48:     {
 49:         context.DeleteObject(entity);
 50:         context.SaveChanges();
 51:         return entity;
 52:     }
 53:     
 54:     public void Dispose()
 55:     {
 56:         context.Dispose();
 57:     }
 58:  }
 

Here is an example of usage in a console application

 1: class Program
 2:  {
 3:    static void Main(string[] args)
 4:    {
 5:      IRepository repository = new EntityFrameworkRepository();
 6:        var page = repository.Get<Page>(x => x.PageId == 1);
 7:        Console.WriteLine("Title: {0}", page.Title);
 8:      Console.WriteLine("Content: {0}", page.Content);
 9:        repository.Dispose();
 10:        Console.ReadLine();
 11:    }
 12:  }

I love taking this approach to persistence because it is so flexible and allows me to swap out repository implementations with little issue.

Again love to hear some feedback on this approach.

Mikael Henriksson’s Original Extension Methods

 1: using System.Data.Metadata.Edm;
 2: using System.Data.Objects;
 3: using System.Data.Objects.DataClasses;
 4:  
 5: public static class ObjectContextExtensions
 6: {
 7:     internal static EntitySetBase GetEntitySet<TEntity>(this ObjectContext context)
 8:     {
 9:         EntityContainer container = context.MetadataWorkspace
 10:                                                         .GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
 11:         Type baseType = GetBaseType(typeof(TEntity));
 12:         EntitySetBase entitySet = container.BaseEntitySets
 13:                                                     .Where(item => item.ElementType.Name.Equals(baseType.Name))
 14:                                                     .FirstOrDefault();
 15:  
 16:         return entitySet;
 17:     }
 18:  
 19:     private static Type GetBaseType(Type type)
 20:     {
 21:             var baseType = type.BaseType;
 22:             if (baseType != null && baseType != typeof(EntityObject))
 23:             {
 24:                 return GetBaseType(type.BaseType);
 25:             }
 26:             return type;
 27:     }
 28: }
blog comments powered by Disqus

Calendar

<<  November 2017  >>
MonTueWedThuFriSatSun
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

Month List