Geeks With Blogs
Juans and Zeros

I am part of a year long plus project that is re-writing an existing application for a client.  We have decided to develop the project using Visual Studio 2012 and .NET 4.5.  The project will be using a number of technologies and patterns to include Entity Framework 5, WCF Services, and WPF for the client UI.

This is my attempt at documenting some of the successes and failures that I will be coming across in the development of the application.

In building the data access layer we have to access a database that has already been designed by a dedicated dba. The dba insists on using Stored Procedures which has made the use of EF a little more difficult.  He will not allow direct table access but we did manage to get him to allow us to use Views. 

Since EF 5 does not have good support to do Code First with Stored Procedures, my option was to create a model (EDMX) against the existing database views.   I then had to go select each entity and map the Insert/Update/Delete functions to their respective stored procedure.

The next step after I had completed mapping the stored procedures to the entities in the EDMX model was to figure out how to build a generic repository that would work well with Entity Framework 5. 

After reading the blog posts below, I adopted much of their code with some changes to allow for the use of Ninject for dependency injection.

http://www.tcscblog.com/2012/06/22/entity-framework-generic-repository/

http://www.tugberkugurlu.com/archive/generic-repository-pattern-entity-framework-asp-net-mvc-and-unit-testing-triangle

IRepository.cs

   
public interface IRepository : IDisposable where T : class
    {
        void Add(T entity);
        void Update(T entity, int id);
        T GetById(object key);
        IQueryable<T> Query(Expression<Func<T,bool>> predicate);
        IQueryable<T> GetAll();
        int SaveChanges();
        int SaveChanges(bool validateEntities);
    }

GenericRepository.cs

    
public abstract class GenericRepository : IRepository where T : class
    {
        public abstract void Add(T entity);
        public abstract void Update(T entity, int id);
        public abstract T GetById(object key);
        public abstract IQueryable<T> Query(Expression<Func<T,bool>> predicate);
        public abstract IQueryable<T> GetAll();
        public int SaveChanges()
        {
            return SaveChanges(true);
        }
        public abstract int SaveChanges(bool validateEntities);
        public abstract void Dispose();
    }

One of the issues I ran into was trying to do an update. I kept receiving errors so I posted a question on Stack Overflow

http://stackoverflow.com/questions/12585664/an-object-with-the-same-key-already-exists-in-the-objectstatemanager-the-object

and came up with the following hack. If someone has a better way, please let me know.

DbContextRepository.cs

 public class DbContextRepository : GenericRepository
        where T : class
    {
        protected DbContext Context;
        protected DbSet<T> DbSet;

        public DbContextRepository(DbContext context)
        {
            if (context == null)
                throw new ArgumentException("context");

            Context = context;
            DbSet = Context.Set<T>();
        }

        public override void Add(T entity)
        {
            if (entity == null)
                throw new ArgumentException("Cannot add a null entity.");

            DbSet.Add(entity);
        }

        public override void Update(T entity, int id)
        {
            if (entity == null)
                throw new ArgumentException("Cannot update a null entity.");

            var entry = Context.Entry(entity);

            if (entry.State == EntityState.Detached)
            {
                var attachedEntity = DbSet.Find(id); // Need to have access to key

                if (attachedEntity != null)
                {
                    var attachedEntry = Context.Entry(attachedEntity);
                    attachedEntry.CurrentValues.SetValues(entity);
                }
                else
                {
                    entry.State = EntityState.Modified; // This should attach entity
                }
            }
        }

        public override T GetById(object key)
        {
            return DbSet.Find(key);
        }

        public override IQueryable Query(Expression> predicate)
        {
            return DbSet.Where(predicate);
        }

        public override IQueryable GetAll()
        {
            return Context.Set<T>();
        }

        public override int SaveChanges(bool validateEntities)
        {
            Context.Configuration.ValidateOnSaveEnabled = validateEntities;
            return Context.SaveChanges();
        }

        #region IDisposable implementation

        public override void Dispose()
        {
            if (Context != null)
            {
                Context.Dispose();
                GC.SuppressFinalize(this);
            }
        }

        #endregion IDisposable implementation
    }


At this point I am able to start creating individual repositories that are needed and add a Unit of Work.  Stay tuned for the next installment in my path to creating a Repository Pattern against EF5.

Posted on Wednesday, October 3, 2012 12:13 PM EF , Patterns , Entity Framework | Back to top


Comments on this post: Building a Repository Pattern against an EF 5 EDMX Model - Part 1

# re: Building a Repository Pattern against an EF 5 EDMX Model - Part 1
Requesting Gravatar...
`public override ``IQueryable`` GetAll` means you have a leaky abstraction. IQueryable alows changing GetAll to a completely different purpose. use IList or IEnumerable instead to define boundaries of your system.
Left by Anon on Jan 20, 2013 1:56 AM

# re: Building a Repository Pattern against an EF 5 EDMX Model - Part 1
Requesting Gravatar...
And where's <T> ? :)
Left by JinX on Mar 17, 2013 9:39 AM

# re: Building a Repository Pattern against an EF 5 EDMX Model - Part 1
Requesting Gravatar...
Annoying how DB-people tends to hold back the future... I did it myself, but then became smarter as I changed my mindset :)
Left by Janus007 on Apr 09, 2013 3:32 PM

# re: Building a Repository Pattern against an EF 5 EDMX Model - Part 1
Requesting Gravatar...
I would change my Interface to be more like

public interface IRepository<TEntity, in TKey> : IDisposable
{
void Add(TEntity entity);
void Update(TEntity entity, int id);
TEntity GetById(TKey key);
bool Contains(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> Query(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> GetAll();
int SaveChanges();
int SaveChanges(bool validateEntities);
}

then make the changes appropriate from there
Left by Gary Woodfine on May 08, 2013 2:19 AM

# re: Building a Repository Pattern against an EF 5 EDMX Model - Part 1
Requesting Gravatar...

A small mistake in my previous comment it should be
<pre>
public interface IRepository<TEntity, in TKey> : IDisposable
{
void Add(TEntity entity);
void Update(TEntity entity, TKey id);
TEntity GetById(TKey key);
bool Contains(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> Query(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> GetAll();
int SaveChanges();
int SaveChanges(bool validateEntities);
}
</pre>
Left by Gary Woodfine on May 08, 2013 2:36 AM

# re: Building a Repository Pattern against an EF 5 EDMX Model - Part 1
Requesting Gravatar...
Really sorry about spamming your comment stream!

But I thought I would just validate why I suggest the Generic key. It is primarily to enable the ability to differentiate between different types of keys. For instance in the application I am working on we use either int or Guid Keys. This implementation caters for that.
Left by Gary Woodfine on May 08, 2013 2:42 AM

Your comment:
 (will show your gravatar)
 


Copyright © JuansAndZeros | Powered by: GeeksWithBlogs.net | Join free