Click here to Skip to main content
Click here to Skip to main content

Implementing Repository Pattern With Entity Framework

By , 2 Nov 2012
 

Introduction  

 

The Repository pattern is defined by Patterns of Enterprise Application Architecture as:   

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects. 

Repository provides an in-memory like collection interface for accessing domain objects. So as far as the consuming component is concerned, it uses the repository just like a collection when working with Domain objects. The repository then neatly abstracts the internal mechanics of how the Add / Remove calls to the repository translate to the actual data access calls to the data store. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.

So with the repository we get a nice abstraction that provides us with persistence ignorance and a nice separation of concerns where the responsibility of persisting domain objects is encapsulated by the Repository leaving the domain objects to deal entirely with the domain model and domain logic.Here are some reasons for using repository pattern in data access layer in place direct access the database code-

  • Duplicated code 
  • A higher potential for programming errors
  • Weak typing of the business data
  • Difficulty in centralizing data-related policies such as caching
  • An inability to easily test the business logic in isolation from external dependencies 

Using the Code 

Here I use the Composite Repository pattern:

    /// <summary>
    /// Repository Interface defines the base
    /// functionality required by all Repositories.
    /// </summary>
    /// <typeparam name="T">
    /// The entity type that requires a Repository.
    /// </typeparam>
    public interface IRepository<E>
    {
        string KeyProperty { get; set; }

        void Add(E entity);
        void AddOrAttach(E entity);
        void DeleteRelatedEntries(E entity);
        void DeleteRelatedEntries
        (E entity, ObservableCollection<string> keyListOfIgnoreEntites);
        void Delete(E entity);

        ObjectQuery<E> DoQuery();
        ObjectQuery<E> DoQuery(ISpecification<E> where);
        ObjectQuery<E> DoQuery(int maximumRows, int startRowIndex);
        ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression);
        ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression,
                    int maximumRows, int startRowIndex);

        IList<E> SelectAll(string entitySetName);
        IList<E> SelectAll();
        IList<E> SelectAll(string entitySetName, ISpecification<E> where);
        IList<E> SelectAll(ISpecification<E> where);
        IList<E> SelectAll(int maximumRows, int startRowIndex);
        IList<E> SelectAll(Expression<Func<E, object>> sortExpression);
        IList<E> SelectAll(Expression<Func<E, object>> sortExpression,
                    int maximumRows, int startRowIndex);

        E SelectByKey(string Key);

        bool TrySameValueExist(string fieldName, object fieldValue, string key);
        bool TryEntity(ISpecification<E> selectSpec);

        int GetCount();
        int GetCount(ISpecification<E> selectSpec);
    }

 

You can write your own Repository for each business object like RoleRepository, UserReporsitory, etc. Or you can implement this interface as a generic class of Repository something like this:   

    public class Repository<E, C> : IRepository<E>
        where E : class
        where C : ObjectContext
    {
        private readonly C _ctx;

        private string _KeyProperty = "ID";

        public string KeyProperty
        {
            get
            {
                return _KeyProperty;
            }
            set
            {
                _KeyProperty = value;
            }
        }

        public C Session
        {
            get { return _ctx; }
        }

        public Repository(C session)
        {
            _ctx = session;
        }

        #region IRepository<E,C> Members

        public int Save()
        {
            return _ctx.SaveChanges();
        }
        /// <summary>
        /// A generic method to return ALL the entities
        /// </summary>
        /// <param name=”entitySetName”>
        /// The EntitySet name of the entity in the model.
        /// </param>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        private ObjectQuery<E> DoQuery(string entitySetName)
        {
            return _ctx.CreateQuery<E>("[" + entitySetName + "]");
        }
        /// <summary>
        /// A generic method to return ALL the entities
        /// </summary>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        public ObjectQuery<E> DoQuery()
        {
            return _ctx.CreateQuery<E>("[" + this.GetEntitySetName( typeof(E).Name) + "]");
        }

        /// <summary>
        /// </summary>
        /// <param name=”entitySetName”>
        /// The EntitySet name of the entity in the model.
        /// </param>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        private ObjectQuery<E> DoQuery(string entitySetName, ISpecification<E> where)
        {
            return
                (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + entitySetName + "]")
                .Where(where.EvalPredicate);
        }

        /// <summary>
        /// </summary>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        public ObjectQuery<E> DoQuery(ISpecification<E> where)
        {
            return
                (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + this.GetEntitySetName( typeof(E).Name ) + "]")
                .Where(where.EvalPredicate);
        }
        /// <summary>
        /// Query Entity with Paging 
        /// </summary>
        /// <param name="maximumRows">Max no of row to Fetch</param>
        /// <param name="startRowIndex">Start Index</param>
        /// <returns>Collection of Entities</returns>
        public ObjectQuery<E> DoQuery(int maximumRows, int startRowIndex)
        {
            return (ObjectQuery<E>)_ctx.CreateQuery<E>
        ("[" + this.GetEntitySetName(typeof(E).Name) + "]").Skip<E>(startRowIndex).Take(maximumRows);
        }
        /// <summary>
        /// Query Entity in sorted Order
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="ErrorCode">custom Error Message</param> 
        /// <returns>Collection of Entities</returns>
        public ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression)
        {
            if (null == sortExpression)
            {
                return this.DoQuery();
            }
            return (ObjectQuery<E>)((IRepository<E>)this).DoQuery().OrderBy
                        <E, object>(sortExpression);
        }
        /// <summary>
        /// Query All Entity in sorted Order with Paging support
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="maximumRows">Max no of row to Fetch</param>
        /// <param name="startRowIndex">Start Index</param>
        /// <returns>Collection Of entities</returns>
        public ObjectQuery<E> DoQuery(Expression<Func<E, object>>
            sortExpression, int maximumRows, int startRowIndex)
        {
            if (sortExpression == null)
            {
                return ((IRepository<E>)this).DoQuery(maximumRows, startRowIndex);
            }
            return (ObjectQuery<E>)((IRepository<E>)this).DoQuery
            (sortExpression).Skip<E>(startRowIndex).Take(maximumRows);
        }
        /// <summary>
        /// A generic method to return ALL the entities
        /// </summary>
        /// <param name=”entitySetName”>
        /// The EntitySet name of the entity in the model.
        /// </param>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        public IList<E> SelectAll(string entitySetName)
        {
            return DoQuery(entitySetName).ToList();
        }
        /// <summary>
        /// A generic method to return ALL the entities
        /// </summary>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        public IList<E> SelectAll()
        {
            try
            {
                return DoQuery().ToList(); //_ctx.CreateQuery<E>("[" + typeof(E).Name + "]");
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// A generic method to return ALL the entities
        /// </summary>
        /// <param name=”entitySetName”>
        /// The EntitySet name of the entity in the model.
        /// </param>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        public IList<E> SelectAll(string entitySetName, ISpecification<E> where)
        {
            return DoQuery(entitySetName, where).ToList();
        }

        /// <summary>
        /// A generic method to return ALL the entities
        /// </summary>
        /// <typeparam name=”TEntity”>
        /// The Entity to load from the database.
        /// </typeparam>
        /// <returns>Returns a set of TEntity.</returns>
        public IList<E> SelectAll(ISpecification<E> where)
        {
            return DoQuery(where).ToList();
        }
        /// <summary>
        /// Select All Entity with Paging 
        /// </summary>
        /// <param name="maximumRows">Max no of row to Fetch</param>
        /// <param name="startRowIndex">Start Index</param>
        /// <returns>Collection of Entities</returns>
        public IList<E> SelectAll(int maximumRows, int startRowIndex)
        {
            return DoQuery(maximumRows, startRowIndex).ToList();
        }
        /// <summary>
        /// Select All Entity in sorted Order
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="ErrorCode">custom Error Message</param> 
        /// <returns>Collection of Entities</returns>
        public IList<E> SelectAll(Expression<Func<E, object>> sortExpression)
        {
            if (null == sortExpression)
            {
                return DoQuery(sortExpression).ToList();
            }
            return DoQuery(sortExpression).ToList();
        }
        /// <summary>
        /// Select All Entity in sorted Order with Paging support
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="maximumRows">Max no of row to Fetch</param>
        /// <param name="startRowIndex">Start Index</param>
        /// <returns>Collection Of entities</returns>
        public IList<E> SelectAll(Expression<Func<E, object>>
            sortExpression, int maximumRows, int startRowIndex)
        {
            if (sortExpression == null)
            {
                return DoQuery(maximumRows, startRowIndex).ToList();
            }
            return DoQuery(sortExpression, maximumRows, startRowIndex).ToList();
        }
        /// <summary>
        /// Get Entity By Primary Key
        /// </summary>
        /// <typeparam name="E">Entity Type</typeparam>
        /// <param name="Key">Primary Key Value</param>
        /// <returns>return entity</returns>
        public E SelectByKey(string Key)
        {
            // First we define the parameter that we are going to use the clause. 
            var xParam = Expression.Parameter(typeof(E), typeof(E).Name);
            MemberExpression leftExpr = MemberExpression.Property(xParam, this._KeyProperty);
            Expression rightExpr = Expression.Constant(Key);
            BinaryExpression binaryExpr = MemberExpression.Equal(leftExpr, rightExpr);
            //Create Lambda Expression for the selection 
            Expression<Func<E, bool>> lambdaExpr =
            Expression.Lambda<Func<E, bool>>(binaryExpr,
            new ParameterExpression[] { xParam });
            //Searching ....
            var resultCollection = (ObjectQuery<E>)_ctx.CreateQuery<E>("[" + this.GetEntitySetName(typeof(E).Name) + "]")
                .Where(lambdaExpr);
            if (null != resultCollection && resultCollection.Count() > 0)
            {
                //return valid single result
                return resultCollection.First<E>();
            }//end if 
            return null;
        }
        /// <summary>
        /// Check if value of specific field is already exist
        /// </summary>
        /// <typeparam name="E"></typeparam>
        /// <param name="fieldName">name of the Field</param>
        /// <param name="fieldValue">Field value</param>
        /// <param name="key">Primary key value</param>
        /// <returns>True or False</returns>
        public bool TrySameValueExist(string fieldName, object fieldValue, string key)
        {
            // First we define the parameter that we are going to use the clause. 
            var xParam = Expression.Parameter(typeof(E), typeof(E).Name);
            MemberExpression leftExprFieldCheck =
            MemberExpression.Property(xParam, fieldName);
            Expression rightExprFieldCheck = Expression.Constant(fieldValue);
            BinaryExpression binaryExprFieldCheck =
            MemberExpression.Equal(leftExprFieldCheck, rightExprFieldCheck);

            MemberExpression leftExprKeyCheck =
            MemberExpression.Property(xParam, this._KeyProperty);
            Expression rightExprKeyCheck = Expression.Constant(key);
            BinaryExpression binaryExprKeyCheck =
            MemberExpression.NotEqual(leftExprKeyCheck, rightExprKeyCheck);
            BinaryExpression finalBinaryExpr =
            Expression.And(binaryExprFieldCheck, binaryExprKeyCheck);

            //Create Lambda Expression for the selection 
            Expression<Func<E, bool>> lambdaExpr =
            Expression.Lambda<Func<E, bool>>(finalBinaryExpr,
            new ParameterExpression[] { xParam });
            //Searching ....            
            return _ctx.CreateQuery<E>("[" + this.GetEntitySetName(typeof(E).Name) + "]").Any<E>
                        (lambdaExpr);
        }
        /// <summary>
        /// Check if Entities exist with Condition
        /// </summary>
        /// <param name="selectExpression">Selection Condition</param>
        /// <returns>True or False</returns>
        public bool TryEntity(ISpecification<E> selectSpec)
        {
            return _ctx.CreateQuery<E>("[" + this.GetEntitySetName( typeof(E).Name ) + "]").Any<E>
                        (selectSpec.EvalPredicate);
        }
        /// <summary>
        /// Get Count of all records
        /// </summary>
        /// <typeparam name="E"></typeparam>
        /// <returns>count of all records</returns>
        public int GetCount()
        {
            return _ctx.CreateQuery<E>("[" + this.GetEntitySetName( typeof(E).Name ) + "]").Count();
        }
        /// <summary>
        /// Get count of selection
        /// </summary>
        /// <typeparam name="E">Selection Condition</typeparam>
        /// <returns>count of selection</returns>
        public int GetCount(ISpecification<E> selectSpec)
        {
            return _ctx.CreateQuery<E>("[" + this.GetEntitySetName( typeof(E).Name ) + "]")
                .Where(selectSpec.EvalPredicate).Count();
        }
        /// <summary>
        /// Delete data from context
        /// </summary>
        /// <typeparam name="E"></typeparam>
        /// <param name="entity"></param>
        public void Delete(E entity)
        {
            _ctx.DeleteObject(entity);
        }
        /// <summary>
        /// Delete data from context
        /// </summary>
        /// <typeparam name="E"></typeparam>
        /// <param name="entity"></param>
        public void Delete(object entity)
        {
            _ctx.DeleteObject(entity);
        }
        /// <summary>
        /// Insert new data into context
        /// </summary>
        /// <typeparam name="E"></typeparam>
        /// <param name="entity"></param>
        public void Add(E entity)
        {
            _ctx.AddObject( this.GetEntitySetName(entity.GetType().Name), entity);
        }
        /// <summary>
        /// Insert if new otherwise attach data into context
        /// </summary>
        /// <param name="entity"></param>
        public void AddOrAttach(E entity)
        {
            // Define an ObjectStateEntry and EntityKey for the current object.
            EntityKey key;
            object originalItem;
            // Get the detached object's entity key.
            if (((IEntityWithKey)entity).EntityKey == null)
            {
                // Get the entity key of the updated object.
                key = _ctx.CreateEntityKey(this.GetEntitySetName(entity.GetType().Name), entity);
            }
            else
            {
                key = ((IEntityWithKey)entity).EntityKey;
            }
            try
            {
                // Get the original item based on the entity key from the context
                // or from the database.
                if (_ctx.TryGetObjectByKey(key, out originalItem))
                {//accept the changed property
                    if (originalItem is EntityObject &&
                        ((EntityObject)originalItem).EntityState != EntityState.Added)
                    {
                        // Call the ApplyCurrentValues method to apply changes
                        // from the updated item to the original version.
                        _ctx.ApplyCurrentValues(key.EntitySetName, entity);
                    }
                }
                else
                {//add the new entity
                    Add(entity);
                }//end else
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// Delete all related entries
        /// </summary>
        /// <param name="entity"></param>        
        public void DeleteRelatedEntries(E entity)
        {
            foreach (var relatedEntity in (((IEntityWithRelationships)entity).
        RelationshipManager.GetAllRelatedEnds().SelectMany(re =>
        re.CreateSourceQuery().OfType<EntityObject>()).Distinct()).ToArray())
            {
                _ctx.DeleteObject(relatedEntity);
            }//end foreach
        }
        /// <summary>
        /// Delete all related entries
        /// </summary>
        /// <param name="entity"></param>        
        public void DeleteRelatedEntries(E entity, ObservableCollection<string>
                            keyListOfIgnoreEntites)
        {
            foreach (var relatedEntity in (((IEntityWithRelationships)entity).
            RelationshipManager.GetAllRelatedEnds().SelectMany(re =>
            re.CreateSourceQuery().OfType<EntityObject>()).Distinct()).ToArray())
            {
                PropertyInfo propInfo = relatedEntity.GetType().GetProperty
                            (this._KeyProperty);
                if (null != propInfo)
                {
                    string value = (string)propInfo.GetValue(relatedEntity, null);
                    if (!string.IsNullOrEmpty(value) &&
                        keyListOfIgnoreEntites.Contains(value))
                    {
                        continue;
                    }//end if 
                }//end if
                _ctx.DeleteObject(relatedEntity);
            }//end foreach
        }

        private string GetEntitySetName(string entityTypeName)
        {
            var container = this._ctx.MetadataWorkspace.GetEntityContainer
                    (this._ctx.DefaultContainerName, DataSpace.CSpace);

            return (from meta in container.BaseEntitySets

                                    where meta.ElementType.Name == entityTypeName

                                    select meta.Name).FirstOrDefault(); 
                     
        }

        #endregion
    }

Notice that, here I also implement IDispose interface to dispose the context manually.To get the name of Entityset, here I have used typeof, but you can do a  metadata query to retrieve the EntitySet name:

container = context.MetadataWorkspace.GetEntityContainer
		(context.DefaultContainerName, DataSpace.CSpace); 

string entitySetName = (from meta in container.BaseEntitySets

                            where meta.ElementType.Name == entityTypeName

                            select meta.Name).FirstOrDefault();   

Here I am not going a little into the code. I have used ObjectQuery to get the features of MargeOption and EnablePlanCaching properties: 

ObjectQuery.EnablePlanCaching Property -indicates whether the query plan should be cached. Plan-caching caches information which is computed as part of putting together the query itself. By caching this, a subsequent execution of the same query (even if you change parameter values) will run much faster than the first one. This information is cached per app-domain so you will generally benefit from the query cache across multiple client requests to the same web app and the like. Here all DoQuery methods are responsible to queries and other query method like SelectAll or Select methods internally use these DoQuery methods with various parameters. 

Setting MergeOption to NoTracking has helped us to take advantage of the EF ability to return data that doesn’t need to be tracked by the context. Say I don’t have any plan to make changes to that data. Therefore, I like to avoid the performance hit taken when EF creates ObjectStateEntry instances for each object it’s tracking, as well as forcing the context to be aware of any changes made to those objects. 

SelectByKey is creating a LINQ expression using Expression tree for Primary key and During creating the repository on an entity you can supply this Primary Key property as string. While using the POCO as you entity you can set attribute programming to serve this kind of job.

TrySameValueExist is doing the same job by allow you to set customize field and value comparison there. What will do is create the Expression for you and also add the PrimaryKey comparison so that it excludes the object that you are querying for (and where PrimaryKey != currentObjectPrimaryKey).

Add and Delete method simply respectively call the AddObject and DeleteObject Method of ObjectContextAddOrAttach method is for special situation where you don’t know whether object is already added or not. It is expensive since it will do query to database to check the existence. 

The specification pattern can implement a re-usable business logic component that can be passed around to satisfy certain business criteria. The specification object has a clear and limited responsibility, which can be separated and decoupled from the domain object that uses it. I would highly recommend reading the white paper by Martin Fowler and Eric Evans on the Specification pattern.   

public interface ISpecification<E>
{
    /// <summary>
    /// Select/Where Expression
    /// </summary>
    Expression<Func<E, bool>> EvalPredicate { get; }
    /// <summary>
    /// Function to evaluate where Expression
    /// </summary>
    Func<E, bool> EvalFunc { get; }
}

You can write your own specification by implementing your interface like RoleSpecification and put down your business logic there. For general use, you can also implement the Interface; such composite specification like this:

    public class Specification<E> : ISpecification<E>
    {
        #region Private Members

        private Func<E, bool> _evalFunc = null;
        private Expression<Func<E, bool>> _evalPredicate;

        #endregion

        #region Virtual Accessors

        public virtual bool Matches(E entity)
        {
            return _evalPredicate.Compile().Invoke(entity);
        }

        public virtual Expression<Func<E, bool>> EvalPredicate
        {
            get { return _evalPredicate; }
        }

        public virtual Func<E, bool> EvalFunc
        {
            get { return _evalPredicate != null ? _evalPredicate.Compile() : null; }
        }

        #endregion

        #region Constructors

        public Specification(Expression<Func<E, bool>> predicate)
        {
            _evalPredicate = predicate;
        }

        private Specification() { }

        #endregion

        #region Private Nested Classes

        private class AndSpecification : Specification<E>
        {
            private readonly ISpecification<E> _left;
            private readonly ISpecification<E> _right;
            public AndSpecification(ISpecification<E> left, ISpecification<E> right)
            {
                this._left = left;
                this._right = right;

                this._evalFunc =
                    (Func<E, bool>)Delegate.Combine
                    (left.EvalPredicate.Compile(),
                    right.EvalPredicate.Compile());

                _evalPredicate = left.EvalPredicate.And(right.EvalPredicate);
            }
            public override bool Matches(E entity)
            {
                return EvalPredicate.Compile().Invoke(entity);
            }
        }

        private class OrSpecification : Specification<E>
        {
            private readonly ISpecification<E> _left;
            private readonly ISpecification<E> _right;
            public OrSpecification(ISpecification<E> left, ISpecification<E> right)
            {
                this._left = left;
                this._right = right;

                this._evalFunc =
                    (Func<E, bool>)Delegate.Combine
                    (left.EvalPredicate.Compile(),
                    right.EvalPredicate.Compile());

                _evalPredicate = left.EvalPredicate.Or(right.EvalPredicate);
            }
            public override bool Matches(E entity)
            {
                return EvalPredicate.Compile().Invoke(entity);
            }
        }

        #endregion

        #region Operator Overloads

        public static Specification<E> operator &(Specification<E> left, ISpecification<E> right)
        {
            return new AndSpecification(left, right);
        }

        public static Specification<E> operator |(Specification<E> left, ISpecification<E> right)
        {
            return new OrSpecification(left, right);
        }

        #endregion

    } 

Here some operator overloading has been applied here is to combine the lambda expression (or predicate) of each specification (left and right side of a composite specification) to create a new lambda expression.This new lambda expression is going to use for querying. So It will help you while you are working with multiple specification already defined as your business rule.  

To use this Repository class from your business layer, one thing I must say that I am sharing a single context in the CRUD process/operation. You must keep alive the context in your entire process of a crud operation. For this, I make a UnitOfWork on top of all.

    public interface IUnitOfWork : IDisposable
    {
        IRepository<TSet> GetRepository<TSet>() where TSet : class;
        DbTransaction BeginTransaction();
        int Save();
    }

Here Unit of Work  has been introduced as umbrella over multiple repositories and shared by all repository in place of the object context directly and method like savetransaction can be switched over there. And here is that implementation. 

    public class UnitOfWork<C> : IUnitOfWork where C : ObjectContext
    {
        private DbTransaction _transaction;
        private Dictionary<Type, object> _repositories;
        private C _ctx;

        public UnitOfWork()
        {
            _ctx = Activator.CreateInstance<C>();
            _repositories = new Dictionary<Type, object>();
        }

        public IRepository<TSet> GetRepository<TSet>() where TSet : class
        {
            if (_repositories.Keys.Contains(typeof(TSet)))
                return _repositories[typeof(TSet)] as IRepository<TSet>;

            var repository = new Repository<TSet, C>(_ctx);
            _repositories.Add(typeof(TSet), repository);
            return repository;
        }
        /// <summary>
        /// Start Transaction
        /// </summary>
        /// <returns></returns>
        public DbTransaction BeginTransaction()
        {
            if (null == _transaction)
            {
                if (_ctx.Connection.State != ConnectionState.Open)
                {
                    _ctx.Connection.Open();
                }
                this._transaction = _ctx.Connection.BeginTransaction();
            }
            return _transaction;
        }

        public int Save()
        {
            return _ctx.SaveChanges();
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (null != _transaction)
            {
                _transaction.Dispose();
            }

            if (null != _ctx)
            {
                _ctx.Dispose();
            }
        }

        #endregion

    }

Repository is kind of mediator to connect business layer with data access. So your business layer should be aware of this repository class. Now, In my BLLRoleManagement class, say I have a method to delete User. That will be something like this:  

///  <summary>
/// Delete User
/// </summary>
/// <param name="userID">User ID</param>
/// <returns>True Or False</return>	   
    public static bool DeleteUser(
    string UserID)
        {
            try
            {
                var unitOfWork = new UnitOfWork<ProjectCodeEntities>();
                var userRepository = unitOfWork.GetRepository<User>();
                using (unitOfWork)
                {
                    using (var transaction = unitOfWork.BeginTransaction())
                    {
                        User UserTobeRemoved = userRepository.SelectByKey(UserID);
                        if (UserTobeRemoved == null)
                            return false;

                        userRepository.DeleteRelatedEntries(UserTobeRemoved);
                        userRepository.Delete(UserTobeRemoved);
                        if (unitOfWork.Save() >= 0)
                        {
                            transaction.Commit();
                            return true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ErrorHandler.WrapException(ex, ErrorCodes.DB_DeleteUser_Error_Code);
            }
            return false;
        } 

Here It will initialize a ObjectContext instance which will be used in you entire process/workflow of an operation. For this, I have provided a factory method inside Unit of Work which create a repository for you using that ObjectContext . Delete all related entities associated with User and then delete User. To share the same context in this delete process, I will call this method like this  

new BLLRoleManagement().DeleteUser(userID);   

 Surely it has a lot of area to improve. I have used some interfaces here those can be used with dependency injection to decouple your code from EF. Hope its help. So here is my end of the discussion on repository pattern implementation with Entity framework. Good luck. 

References: 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Morshed Anwar
Team Leader Adaptive Enterprise Limited (www.ael-bd.com)
Bangladesh Bangladesh
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
SuggestionRepository for Entity Framework Code-first (DbContext)memberMorshed Anwar3-Oct-12 21:46 
Please note, A Entity Framework- Code First Version has been written by ME as
Repository pattern with Entity Framework Code-First in Composable Service End
Md. Morshed Anwar | Senior Software Engineer
Adaptive Enterprise Limited
Blog: http://morshedanwar.wordpress.com/

SuggestionSuggest that you update it for dbContext & MVC4memberMember 8897653-Aug-12 13:21 
Picking up on your most recent comment:
 
It has been published about three years ago and it has been writing on ef v1.1.
 
Given the amount that's changed since the original post:
-- The Opinions and Conventions of MVC have matured
-- EF Code First makes EF far more accessible (and therefore: mainstream)
-- 3rd party utilities have matured
-- Experience levels of senior-level devs has matured
 
The rigor and thoroughness you've applied to the explanation would be all that much more valuable if you undertook a more comprehensive re-write.
GeneralRe: Suggest that you update it for dbContext & MVC4memberMorshed Anwar3-Oct-12 21:43 
A Entity Framework- Code First Version has been written by ME as
Repository pattern with Entity Framework Code-First in Composable Service End
Md. Morshed Anwar | Senior Software Engineer
Adaptive Enterprise Limited
Blog: http://morshedanwar.wordpress.com/

Question[My vote of 1] sorry but no...memberLeonardo Paneque11-May-12 10:15 
Sorry but I can not give this more than 1.
 
this is a typical case of over-architecting.
A pattern is useful not just because you can use it to prove you can do "correct design" or using the "good practices", it is useful because it can give you something: flexibility, speed, test-ability, scalability, etc.
 
you need to consider that EF already have Repository and UoW implemented. so, if you are about to wrap that in a second layer. That should be "easier" to use than just using EF directly.
 
Because of "repositories" like this is that some developers like Ayende hate the repository pattern http://ayende.com/blog/3955/repository-is-the-new-singleton[^]
 
I disagree with Ayende's extremist point view, I think you can use repository and UoW and make some good out of it (sometimes). But it needs to be done more simple.
 
You have used hundreds of lines of code for something that is achievable on less than 30 lines of code (including IoC, UoW and POCO). No to mention what you have done with the KEY...
 
Sorry but if you are using a pattern to is supposed to make things easier, and is not doing it, then you are using it the wrong way.
Leonardo Paneque

AnswerRe: [My vote of 1] sorry but no... [modified]memberMorshed Anwar12-May-12 2:10 
Thanks for your judgement!! its not on "good practices" mood,it help me to have a single entry point of all
db related code, implementing Logging and Caching , audit trial ....its totally up to you whether you want it or not ....its just an concept that I share and Im sure it helps some people get some ready to use code. ....yes, Surely , I also feel there is always some areas of improvement...and this article has that also....I am not worry about anybody's vote , all I am worry about reader's feedback that I may missed here. It has been published about three years ago and it has been writing on ef v1.1.

modified 12-May-12 9:24am.

AnswerRe: [My vote of 1] sorry but no...membernportelli3-Apr-13 5:52 
So EF implements UoW and Repository patterns, or so I've heard. Yet I've never seen a good example of how to use EF properly WITHOUT it being directly in the presentation layer. In my case a MVC project. Please if you know of a simpler implementation, share it.
GeneralRe: [My vote of 1] sorry but no...memberLeonardo Paneque3-Apr-13 6:38 
They do implement those patterns, a DbContex or ObjectContext would be your UoW, and the ObjectSet or Set inside are your repositories, then, there is no need to rebuild the pattern around the pattern.
 
so, if you have a UoW you use it in your site from the presentation layer right? why not EF then? now, if the problem is that you dont want dependencies/references to EF (which makes sense) I would recommend to use Unity Framework and inject those into your project. All you need to do is wrap that around with an interface that return IQueryable.
 
IQueryable is the center of all here, is what makes those pattern-wrapping obsolete, when Martin Fowler wrote that in the book, he referred to "collections", and IQueryable is more powerful than that.
Leonardo Paneque

GeneralRe: [My vote of 1] sorry but no...membernportelli3-Apr-13 7:54 
Actually our presentation layer would call services, which would then call the DB or UoW, but same difference. Abstracting out EF is not my intention, I'd rather have testable code. IE I don't want to have to use a database to test code. I've always assumed this was the reason people implemented their own UoW and Repository patterns. I suppose I'll go look and see how testable EF is on it's own.
 
And I certainly plan on using a dependency injection framework. Unfortunately I learn from example and most examples out there are so trivial they are useless when it comes to wiring all this up in a real app that doesn't get things one entity at a time.
 
Thank you.
QuestionGreat!memberLaserson24-Jan-12 7:18 
Nice article, thanks.
 
But how can i use it with dependency injection?
QuestionHow to use SQL Server View?memberSunasara Imdadhusen17-Oct-11 4:03 
Hi
Morshed Anwar,
 
Excellent code you have published for us. thanks for sharing with us. My vote of 5
 
Can you explain how to call SQL View using Repository Pattern and Entity Framework 4.0 wit MVC 3.0?

Any answer would be appreciated!.
Thanks,
Imdadhusen

sunaSaRa Imdadhusen
+91 99095 44184

QuestionInteresting! But would this approach work with the entities with multiple primary keys?memberRahman Mahmoodi13-Aug-11 16:11 
This sounds good to have a generic repository, but would this approach work for entities with multiple primary keys?
QuestionHow are you creating the _ctx object?memberkaschimer2-Jun-11 3:57 
I see in your code you create _ctx with:
 
_ctx = Helper.SecurityContextInstance;
 
I am new to EF and was wondering what your Helper method/property looks like??
"Those that say a task is impossible shouldn't interrupt the ones who are doing it." - Chinese Proverb

QuestionWCF?memberInian6-Apr-11 13:31 
Any thoughts on how to implmenet this generic repository in a WCF service? It doesn't seem to support Generics, where you have to provide a concrete type while instantiating. Thanks.
Generalgreat article - working with where, join, other clausesmemberMauricio Sanchez28-Mar-11 6:01 
Hello,
 
Thanks for this article, makes the pattern really easy to use. One questions though, this may sound dummy as I am new to LinQ, how can I use your example with Linq some more complex queries?
Consider this example:
var myList = from a in _db.apples
join p in _db.oranges on a.idequals p.Id
where a.color == p.color
select p ;
Or perhaps a sample that works with a function parameter
var myList = from a in _db.apples
join p in _db.oranges on a.idequals p.Id
where a.color == PARAM
select p ;
In addition would you please provide an example on how to use those methods that work with the ISpecification?
 
Thanks a lot!
GeneralRe: great article - working with where, join, other clausesmemberMauricio Sanchez30-Mar-11 5:51 
Never mind, I figured it out... Thanks
GeneralMy vote of 5memberMember 150559020-Jan-11 1:26 
Perfect
QuestionUsing static methods.memberMartinSpasovski19-Jan-11 9:22 
First, this is a great starting reference for Repository patterns. I have modified your repository to support POCO and have tested and works nice.
 
Second, I have a question about using static methods such as
public static Setting GetSettingByID(int settingID)
{ 
     return (Setting)settingsRepo.Single(p=>p.SettingID == settingID)
}
 
my class is structured as
public class SettingBLL
{
        private static Repository<Setting, EntityModel> settingsRepo;
        static SettingBLL()
        {
            EntityModel db = new EntityModel();
            settingsRepo = new Repository<Setting, EntityModel>(db);
        }
 
        public static Setting GetSettingByID(Int32 settingID)
        {
            return (Setting)settingsRepo.Single(param => param.SettingID == settingID);
        }
}
 
As you know, you mention that the context lifetime should be kept as long as the class/BLL workflow will be executed. Then the context should be disposed with the implementation of IDisposable. But this is in a case when we instantiate the class, and not the case when we have static methods. So i had to abandon the Dispose because later in the front end code a if a call is made again to the SettingBLL, the current that executed is disposed and since i am calling a static method the class will not be constructed again, nor the context will be kept alive for long enough.
 
Are there any implications of using the repository pattern as such, will it consume more memory, what will be the performance issues that i can expect?
 
Thanks, Martin.
AnswerRe: Using static methods.memberchjerome30-Mar-11 10:09 
Hi Martin,
 
I'm currently working with this implementation of repository and I just read that you modify to support POCO.
 
I would like to do it myself, but I can find the way to do it.
 
So, it would be nice if you can share it Smile | :) (or if you can explain your approach)
 
Thank you in advance,
 
Jerome
QuestionCompound Key supportmembertr1stan9-Dec-10 3:24 
Hi Morshed,
 
Do you plan on supporting Compound Keys on an Entity (an entity who's tables primary key is made up of two or more Foreign Keys)?
 
Thanks again for your excellent work.
GeneralNot ComipilingmemberGana3-Dec-10 15:26 
Hello,
 
can you please post the code. Since the classes you have provided does not seem to compile.
 
Thanks in advance.
Ganapatsa
GeneralRe: Not ComipilingmemberGana3-Dec-10 15:36 
Had missed out using clause of system.linq. after that it compiles
GeneralHelpmemberSanjayDhooom17-Nov-10 12:56 
This is really good artical you have wirtten. But still its is giving me error. Can you please give me solution if possible for this so that I can see what I am doing wrong.
 

 
Thank you,
Sanjay
Questioncan you share this POCO with Repository Patternmemberraghuram Muvvala9-Aug-10 10:56 
Hi
I couldn't find the download for the POCO with Repository Pattern can you please let me know if I am missing something.
 
Regards,
Ram
GeneralWorking with multiple entities [modified]memberHari Krishn2-Aug-10 14:19 
Hello Morshed,
Thanks for the great article. I have couple of questions in dealing with relationships.
 
1. With foreign key relationship:
 
In the first scenario, assume we have two tables: Order and OrderDetails. Order.OrderId is the primary key in Order table and the OrderDetail.OrderId is the foreign key.
 
How do you include the orderdetails in the following code?
 
public List<Order> GetOrderDetails(ISpecification<Order> where)
{
   Repository<Order, OrderEntities> orderRepo = new Repository<Order, OrderEntities>;
   orderRepo.DoQuery("Order", where);
}
 
2. Without foreign key relationship:
 
In the second scenario, we still have the above two tables, but the OrderDetail.OrderId is not defined as a foreign key in the database.
 
How do we retrieve OrderDetails in this case?
 
Regards,
Hari.

modified on Monday, August 2, 2010 8:49 PM

GeneralRe: Working with multiple entities [modified]memberBillW4227-Aug-10 9:16 
DoQuery returns an ObjectQuery. This functions just like LINQ statements. The Session property is the context that can be used to join additional tables.
 
from o in orderRepo.DoQuery(where)
    join od in orderRepo.Session.OrderDetails on o.OrderId equals od.OrderId
    where o.modifiedDate > since
    select new OrderWithDetail 
    {
        Order = o,
        OrderDetail = od,
    }
 
or if there this is a one to many,
public class OrderWithManyDetail{
    public Order {get;set;}
    public IEnumerable<OrderDetail> OrderDetails {get;set;}
}
 
...
 
    from o in orderRepo.DoQuery(where)
    where o.modifiedDate > since
    select new OrderWithManyDetail 
    {
        Order = o,
        OrderDetail = from od in orderRepo.Session.OrderDetails
            where od.OrderId == o.OrderId 
            select od,
    }

modified on Friday, August 27, 2010 4:36 PM

QuestionWCF & IRepository [modified]memberurnelson3-Jun-10 11:18 
Hi Morshed Anwar,
 
this is a great article, thanks for share.
 
how can I present in WCF the IRepository?
 
Thank you,
Neo

modified on Thursday, June 3, 2010 5:37 PM

AnswerRe: WCF & IRepositorymemberMorshed Anwar30-Jun-10 0:26 
If your Business layer and DAL on server side, why do you want the repository on client? for V1, it has an N-tier issue. service layer will expose domain objects only.If all you want is a thin CRUD layer exposed as a web service, then WCF data service will do that for you.
GeneralGreat article!!!memberjakka3010-May-10 12:52 
Hi Morshed Anwar,
 
This is a cool article with loads of information. Here are few questions or concerns about it.
 
a. You are using an ObjectContext per repository. I like this idea, but the life time of it making me nervous. As you know, over the time the memory consumption of object context can dramatically increase as it keeps track of old vlaues and new values...etc. I am new to Entity Framework, so please pardon my ignorance.
 
b. You are using DbTransaction to perform critical database operations. My question is, will object context keep tracking the data, even though dbConnection is Closed?
 
Thank you,
Suresh
GeneralRe: Great article!!!memberMorshed Anwar11-May-10 22:20 
Suresh.. .thank you so much for the compliment. As I said in article, you just have to keep alive context in a workflow only and share the context in all created repositories in a workflow. After competing a workflow it can be disposed. So its completely depend on your using.
The Entity Framework opens connections only when required, for example to execute a query or to call SaveChanges, and then closes the connection when the operation is complete and it exposes the EntityConnection through the Connection property. This enables you to manage the connection and transactions or to supply your own EntityConnection. When you manually open the connection in a long-running object context, you must call the Dispose method to ensure that the connection is closed when the context is no longer needed. You can also call the Close method on the EntityConnection to explicitly close the connection. For more information, see .How to: Manage the Connection in a Long-Running Object Context (Entity Framework) . Any streaming type data access (DataReader) will not work after the dispose because the connection will be closed. Moving items into a list will get around this problem and EF use this internally. So I think it shouldn't be work.
GeneralTryGetObjectByKeymemberabellix26-Apr-10 10:32 
How does it work TryGetObjectByKey in the AddOrAttach function?
It works fine but I'm pretty confused. D'Oh! | :doh:
 
1. Get the entity key
2. Get the original item with TryGetObjectByKey
3. Call the ApplyPropertyChanges method passing the entity key
 
Why do you get the original item if it is never used?
Without that it won't work, of course Shucks | :->
 
Be kind with me, I'm very new at EF Sigh | :sigh:
 
Thanks for your article and for any help you'll give me Smile | :)
GeneralRe: TryGetObjectByKeymemberMorshed Anwar27-Apr-10 1:14 
I have used TryGetObjectByKey to ensure the attachment of the orginal item in the context. In EF, it lookes up for data from db, when you tell it to do so. Before calling ApplyPropertyChanges, I need the orginal item present in the context. Then ApplyPropertyChanges compare the scaler properties of new object with old one.
GeneralRe: TryGetObjectByKeymemberabellix27-Apr-10 8:05 
Thank you for your fast answer.
 
So TryGetObjectByKey loads the old values, ApplyPropertyChanges somehow will compare them with the currents. Not so transparent, but now it's clearer Big Grin | :-D
GeneralRe: Entity Framework made me feel sickmemberGermyan23-Feb-10 21:39 
EF sucks, that is true
QuestionSlow?memberBoyfer7-Feb-10 12:54 
The patterns is really nice, but I see a lot of code here, fortunatelly we are not using the JVM; but is this code fast? What happend if I really need performance in my app?
AnswerRe: Slow?memberMorshed Anwar7-Feb-10 20:09 
Design Patterns are about capturing reusable solutions to software engineering problems. If you are worry about you application performance then first you need to decide whether you are going to use ORM or not. I don't have the idea about your application volume. Its true that when you are implementing some pattern , you may need to wrap your objects. Wrapping is expensive, and fpr the same reason any ORM is expensive in compare to use native SQL code. From my point of view, benefit of using pattern is much more then its cost. So Don't need to worry about that. to know about the FE performance,you can read a nice post here. Aywaz I am also a Java Fan, I don't think that you have to worry about implementing any pattern in Java. Smile | :)
QuestionHow to implement specification and sortingmembersan32972-Feb-10 6:01 
Hi thanks for a great article.I implemented exactly the way specified everything works fine.But how should i implement specification with sorting.For example in my case i want to get rows only which satisfy my condition followed by sortexpression,then loading them into grid by sending rowindex and max rows.Thanks.
QuestionObjectQuery Vs IQueryablememberMember 425624822-Jan-10 15:19 
Fantastic article. It has proved invaluable for my project, however I have a question,
 
Can you please explain why you have chosen to return an ObjectQuery(Of T) for DoQuery rather than IQueryable(Of T)?
 
From what I have read (and experienced in my project), the type ObjectQuery cannot be mocked as it is not an abstract class whereas it's base class IQueryable can be, I have made this change in my project and it has passed the litmus test (ie I can still retrieve data).
AnswerRe: ObjectQuery Vs IQueryablememberMorshed Anwar26-Jan-10 0:39 
No specific reason. Thanx for sharing your experience. When the query has been processed, it's no longer an IQueryable, becomes an ObjectQuery.But At design time, the compiler recognizes that it's a LINQ query and therefore assumes the return will be an IQueryable. So sure you can change/cast it into IQueryable.
GeneralSort ExpressionmemberAMBS - TI28-Dec-09 6:41 
I'm developing a prototype using your repository implementation and I', having some difficulties in understating how to pass a sortExpression to the Selectall method when I want to sort, for example, by a DateTime field?
 
Since de lambda expression is expecting an object type, it automatically inserts “Convert” into the expression.
 
I’m using the following code:
 
return repository.SelectAll(o => o.NewsDate, 10, 1);
 
Thnsk for the help.
 
Thanks,
Antonio
GeneralRe: Sort ExpressionmemberMorshed Anwar30-Dec-09 20:36 
I didn't understand ur sample code. Honestly speaking I cant get time to run my sample code to reproduce the issue. If you need a quick solution for this . please check the forum post -
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/b3537995-2441-423d-8485-ee285cf2f4ba[^]
 
is that similar to the issue ? post the error details. You can also mail me the details at - simplyananto at yahoo dot com.
I will see into this issue whenever I will get some time.
GeneralRe: Sort ExpressionmemberAMBS - TI31-Dec-09 1:49 
The error message is: Unable to cast the type 'System.DateTime' to type 'System.Object'. LINQ to Entities only supports casting Entity Data Model primitive types.
 
Thanks
GeneralRe: Sort Expressionmembernamesemail18-Jan-10 6:58 
IList<Project> list = 
          (from x in _repository.DoQuery(p => p.StatusDate, maxrows, startrow)
            select x).ToList();
 
So far this Repository implementation is impeccable and fits very well in to a solution I am working on. Thank you for your effort; it has helped a lot.
 
I am having trouble with Ordering/Sorting however; similar to Antonio's problem.
 
When I try to run the above code, I get the same Casting Error already mentioned in this thread. (unable to cast to System.DateTime)
 
None of the methods using "sortExpression" allow sorting, and any DoQuery(int maxrows, int startrow) calls fail with a message stating you must "OrderBy" before you "Skip".
 
I'm sure it's something I'm doing but could you maybe provide a working example of your code, using the DoQuery(sortExpression, maxrows, startrow) method?
GeneralRe: Sort ExpressionmemberMorshed Anwar19-Jan-10 2:22 
I am very much sorry for the trouble. I am going to change the method signature and make it Generic in place of 'object' type as result parameter. The change will be like this -
 
previous signature was -

ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression);
ObjectQuery<E> DoQuery(Expression<Func<E, object>> sortExpression,
int maximumRows, int startRowIndex);
IList<E> SelectAll(Expression<Func<E, object>> sortExpression);
IList<E> SelectAll(Expression<Func<E, object>> sortExpression,
int maximumRows, int startRowIndex);

 
New methods will be -

ObjectQuery<E> DoQuery<T>(Expression<Func<E, T>> sortExpression);
ObjectQuery<E> DoQuery<T>(Expression<Func<E, T>> sortExpression, int maximumRows, int startRowIndex);
IList<E> SelectAll<T>(Expression<Func<E, T>> sortExpression);
IList<E> SelectAll<T>(Expression<Func<E, T>> sortExpression, int maximumRows, int startRowIndex);

 
So now these method will be sothing like these
        /// <summary>
        /// Query Entity in sorted Order
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="ErrorCode">custom Error Message</param> 
        /// <returns>Collection of Entities</returns>
        public ObjectQuery<E> DoQuery<T>(Expression<Func<E, T>> sortExpression)
        {
            if (null == sortExpression)
            {
                return ((IRepository<E, C>)this).DoQuery();
            }
            return (ObjectQuery<E>)((IRepository<E, C>)this).DoQuery().OrderBy<E, T>(sortExpression);
        }
        /// <summary>
        /// Query All Entity in sorted Order with Paging support
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="maximumRows">Max no of row to Fetch</param>
        /// <param name="startRowIndex">Start Index</param>
        /// <returns>Collection Of entites</returns>
        public ObjectQuery<E> DoQuery<T>(Expression<Func<E, T>> sortExpression, int maximumRows, int startRowIndex)
        {
            if (sortExpression == null)
            {
                return ((IRepository<E, C>)this).DoQuery(maximumRows, startRowIndex);
            }
            return (ObjectQuery<E>)((IRepository<E, C>)this).DoQuery<T>(sortExpression).Skip<E>(startRowIndex).Take(maximumRows);
        }
        /// <summary>
        /// Select All Entity in sorted Order
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="ErrorCode">custom Error Message</param> 
        /// <returns>Collection of Entities</returns>
        public IList<E> SelectAll<T>(Expression<Func<E, T>> sortExpression)
        {
            if (null == sortExpression)
            {
                return DoQuery(sortExpression).ToList();
            }
            return DoQuery(sortExpression).ToList();
        }
        /// <summary>
        /// Select All Entity in sorted Order with Paging support
        /// </summary>
        /// <param name="sortExpression">Sort Expression/condition</param>
        /// <param name="maximumRows">Max no of row to Fetch</param>
        /// <param name="startRowIndex">Start Index</param>
        /// <returns>Collection Of entites</returns>
        public IList<E> SelectAll<T>(Expression<Func<E, T>> sortExpression, int maximumRows, int startRowIndex)
        {
            if (sortExpression == null)
            {
                return DoQuery(maximumRows, startRowIndex).ToList();
            }
            return DoQuery(sortExpression, maximumRows, startRowIndex).ToList();
        }
 
I am going to update the example source also. Please let me knoe if you get any trouble to work with this. Download the new example source
GeneralRe: Sort ExpressionmemberSteveInTexas20-Jan-10 4:13 
Bingo. Those changes work great.
 
Thanks again Morshed.
GeneralRe: Sort ExpressionmemberMorshed Anwar20-Jan-10 18:37 
no problem. Smile | :)
GeneralPlease rate this Article whatever you think on this.memberMorshed Anwar26-Nov-09 17:53 
Please rate this Article whatever you think about this article.That will help me to write my next one.
GeneralExcellentmembercyrilvincent26-Nov-09 9:37 
I'm French, my English is very badUnsure | :~
 
I have the same class for NHibernate & Linq2Sql
But I never know how to do the SelectByKey method for EF : Thanks a lot Laugh | :laugh:
 
Question : I want to inherits a entity object generated by EF from a POCO AbstractClass or Interface, is it possible ?
 
Cyril
GeneralRe: Excellent [modified]memberMorshed Anwar26-Nov-09 17:37 
no problem Cyril....my pleasure to share my thoughts wid u.
I am Bangali, and my english is also very bad:S. :P
so the answer is , I never try the scenario you have mentioned.
But I think it should work.EntityObject implements the 3 interfaces- IEntityWithChangeTracker, IEntityWithKey,IEntityWithRelationships. Apart from these interfaces, EntityObject also implements StructuralObject which its uses to set field values for properties as Zeshaan said in his tutorial.
you have to marked the class with EdmEntityTypeAttribute which tells entity framework that your POCO class in an entity. EdmEntityTypeAttribute attribute takes two parameters. First parameter represents the namespace where the entity resides and second parameter specifies the name of the entity.
 
Md. Morshed Anwar
 
modified on Thursday, November 26, 2009 11:47 PM

QuestionBest way to implement eager loadingmembertr1stan9-Nov-09 5:30 
After looking through your code, which has been a great read btw, I can't seem to see how you approach the issues of eager loading child object using this generic repository.
 
Am I missing something here, or is it outside of the scope of the repository interface?
 
I was thinking about something like, in a very basic form to illustrate an idea:
 
   
public ObjectQuery<E> DoQuery(string include)
{
   return entities.CreateQuery<E>("[" + typeof(E).Name + "Set]").Include(include);
}
 
or perhaps using a string array to construct a dot-seperated list for the Include method.
AnswerRe: Best way to implement eager loadingmemberMorshed Anwar10-Nov-09 23:40 
Thank you so much for the sharing. Yes you are right. Here I didn't implement any approach of eager loading child object. This was just an sample. You can add more methods if u need.
The example that you have provided is ok but I wanna share something with you -
"[" + typeof(E).Name + "Set]" is ok but EDMX has the option to change the entity set name. Its better to retrieve the entity set name from metadata query.
 
To Avoid the string parameter ,you can consider a very good read here

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130617.1 | Last Updated 2 Nov 2012
Article Copyright 2009 by Morshed Anwar
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid