2

I am using entity framework 4 and I have many tables (500). My edmx file is very large and I find it really hard to open it and make changes on it. I found that in my project there are "groups" of tables that related to specific business so I would like to saperate the edmx into several files. I am using repository pattern and unit of work pattern and work with POCOs this way:

This is my container
    public partial class MyEntities : ObjectContext {
        #region Private Methods
        private void SetContextOptions() {
            ContextOptions.LazyLoadingEnabled = false;
        }
        #endregion

        #region Constructors
        public MyEntities()
            : base("name=MyConnection", "MyEntities") {
            SetContextOptions();
            OnContextCreated();
        }
        #endregion

        #region Partial Methods
        partial void OnContextCreated();
        #endregion
    }

For each edmx I will set the Entity Container Name property to MyEntities. This is my generic repository:

public class Repository<T> : IRepository<T> where T : class, IDataEntity
{
    ObjectContext _context;
    IObjectSet<T> _objectSet;

    protected ObjectContext Context
    {
        get
        {
            if (_context == null)
            {
                _context = GetCurrentUnitOfWork<EFUnitOfWork>().Context;
            }

            return _context;
        }
    }

    protected IObjectSet<T> ObjectSet
    {
        get
        {
            if (_objectSet == null)
            {
                _objectSet = this.Context.CreateObjectSet<T>();
            }

            return _objectSet;
        }
    }

    public TUnitOfWork GetCurrentUnitOfWork<TUnitOfWork>() where TUnitOfWork : IUnitOfWork
    {
        return (TUnitOfWork)UnitOfWork.Current;
    }       

    public virtual IQueryable<T> GetQuery(IEnumerable<Expression<Func<T, object>>> includes)
    {
        return ObjectSet.IncludeMultiple(includes);
    }

    public virtual IPaged<T> GetQuery(IQueryable<T> query,
        Func<IQueryable<T>, IOrderedQueryable<T>> orderBy, int pageNumber, int pageSize)
    {
        if (orderBy != null)
        {
            query = orderBy(query);
        }

        IPaged<T> page = new Paged<T>(query, pageNumber, pageSize);

        return page;
    }

    public virtual IPaged<T> GetQuery(IEnumerable<T> query,
        Func<IEnumerable<T>, IOrderedEnumerable<T>> orderBy, int pageNumber, int pageSize)
    {
        if (orderBy != null)
        {
            query = orderBy(query);
        }

        IPaged<T> page = new Paged<T>(query, pageNumber, pageSize);

        return page;
    }

    public virtual IEnumerable<T> GetObjectStateManagerChanges()
    {
        return this.Context.ObjectStateManager.
            GetObjectStateEntries(EntityState.Added | EntityState.Modified).
            Select(e => e.Entity).
            OfType<T>();
    }

    public virtual void Insert(T entity)
    {
        this.ObjectSet.AddObject(entity);
    }

    public virtual void Delete(T entity)
    {
        this.ObjectSet.DeleteObject(entity);
    }

    public virtual void MarkModified(T entity)
    {
        this.Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
    }

    public virtual void Attach(T entity)
    {
        ObjectStateEntry entry = null;
        if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == false)
        {
            this.ObjectSet.Attach(entity);
        }
    }

    public virtual void Detach(T entity)
    {
        ObjectStateEntry entry = null;
        if (this.Context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry) == true)
        {
            this.ObjectSet.Detach(entity);
        }
    }

    public virtual T GetOriginalEntity(Func<T, bool> predicate)
    {
        T originalEntity = null;
        EFUnitOfWorkFactory factory = new EFUnitOfWorkFactory();
        using (EFUnitOfWork uow = (EFUnitOfWork)factory.Create())
        {
            originalEntity = uow.Context.CreateObjectSet<T>().Single(predicate);
        }
        return originalEntity;
    }
}

And this is my unit of work implementation:

    public class EFUnitOfWorkFactory : IUnitOfWorkFactory
    {
        private static int Counter = 0;
        private static Func<ObjectContext> _objectContextDelegate;
        private static readonly Object _lockObject = new object();

        public static void SetObjectContext(Func<ObjectContext> objectContextDelegate)
        {
            _objectContextDelegate = objectContextDelegate;
        }

        public IUnitOfWork Create()
        {
            ObjectContext context;

            lock (_lockObject)
            {
                Counter++;
                context = _objectContextDelegate();
            }

            return new EFUnitOfWork(context, Counter);
        }
    }

public class EFUnitOfWork : IUnitOfWork, IDisposable
    {
        public ObjectContext Context { get; private set; }
        public int Id { get; private set; }

        public EFUnitOfWork(ObjectContext context, int id)
        {
            Id = id;
            Context = context;
            Context.ContextOptions.LazyLoadingEnabled = false;
        }

        public int Commit()
        {
            return Context.SaveChanges();
        }

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

            GC.SuppressFinalize(this);
        }
    }

will my plan work to divide the edmx work with this code? What is the best practices for my case (I have read the two parts of http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-1.aspx)?

EDIT: When trying to set the entity container names of the edmxs to MyEntities, I get:

EntityContainer name 'MyEntities' is already in use by another Entity Data Model in the project.

Is there any workaround?

Naor
  • 23,465
  • 48
  • 152
  • 268
  • Here is a very good answer with links on how to do it: http://stackoverflow.com/questions/3867479/entity-framework-4-does-it-make-sense-to-create-a-single-diagram-for-all-entiti/3868075#3868075 – Ryan Drost Jun 26 '12 at 23:37
  • @RyanDrost: This answer is exactly what I already read . I don't find it's solution practical enough. – Naor Jun 27 '12 at 06:29
  • @RyanDrost: The solution you provided doesn't use poco, repository pattern and not unit of work. Moreover, it is the same as creating several edmxs, just with reuse of the csdl. – Naor Jun 29 '12 at 14:00

1 Answers1

0

Naor,

You need to Generate a poco Class for this entity it automatically create pococlasses for right click in entity which you have created ,you able to view options in that in that click on code generator in that you need to select E4 entitypocogenrator it automatically create object context and pococlass those classes are partial class we need to separate which we want. if you are unable to find E4enitypocogenrater you need to install this one here is the link to instal the poco class fr Ado.entity frame work http://visualstudiogallery.msdn.microsoft.com/23df0450-5677-4926-96cc-173d02752313/

User
  • 11
  • 5
  • I appriciate your effort but I think you didn't understand my question. I am only trying to split my edmx file. – Naor Jul 18 '12 at 13:32
  • For Linq-to-SQL, there are a number of alternatives which allow you to create more granular sets of files, rather than one single HUGE file. Please check this link http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/cc49ad21-5c99-4709-bf5f-3dfae022d240/ Check out PLINQO - a CodeSmith template set - http://www.plinqo.com - very well done, allows you to update your model from the database, and creates one code file per object class. – User Jul 19 '12 at 06:50