Entity Framework - работа с несколькими файлами edmx

Я использую Entity Framework 4, и у меня много таблиц (500). Мой файл edmx очень большой, и мне очень трудно открыть его и внести в него изменения. Я обнаружил, что в моем проекте есть «группы» таблиц, связанных с конкретным бизнесом, поэтому я хотел бы разделить edmx на несколько файлов. Я использую шаблон репозитория и шаблон единицы работы и работаю с POCO следующим образом:

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
    }

Для каждого edmx я установлю для свойства Entity Container Name значение MyEntities. Это мой общий репозиторий:

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;
    }
}

И это моя единица реализации работы:

    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);
        }
    }

сработает ли мой план, чтобы разделить работу edmx с этим кодом? Что лучше всего подходит для моего случая (я прочитал две части http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-1.aspx)?

EDIT: При попытке установить имена контейнеров сущностей edmxs в MyEntities я получаю:

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

Есть ли обходной путь?


person Naor    schedule 23.06.2012    source источник
comment
Вот очень хороший ответ со ссылками на то, как это сделать: stackoverflow.com/questions/3867479/   -  person Ryan Drost    schedule 27.06.2012
comment
@RyanDrost: это именно тот ответ, который я уже читал. Я не нахожу это решение достаточно практичным.   -  person Naor    schedule 27.06.2012
comment
@RyanDrost: Предоставленное вами решение не использует poco, шаблон репозитория и не единицу работы. Более того, это то же самое, что создать несколько edmx, только с повторным использованием csdl.   -  person Naor    schedule 29.06.2012


Ответы (1)


Наор,

Вам нужно сгенерировать класс poco для этого объекта, он автоматически создает pococlasses для щелчка правой кнопкой мыши в объекте, который вы создали, вы можете просматривать параметры в этом щелчке по генератору кода, в котором вам нужно выбрать E4 entitypocogenrator, он автоматически создает контекст объекта и pococlass, эти классы являются частичными классами, которые нам нужно разделить, которые мы хотим. если вы не можете найти E4enitypocogenrater, вам необходимо установить его, вот ссылка для установки класса poco из фреймворка Ado.entity http://visualstudiogallery.msdn.microsoft.com/23df0450-5677-4926-96cc-173d02752313/

person User    schedule 18.07.2012
comment
Я ценю ваши усилия, но я думаю, что вы не поняли мой вопрос. Я только пытаюсь разделить свой файл edmx. - person Naor; 18.07.2012
comment
Для Linq-to-SQL существует ряд альтернатив, которые позволяют создавать более детализированные наборы файлов, а не один ОГРОМНЫЙ файл. Пожалуйста, проверьте эту ссылку социальная .msdn.microsoft.com/Forums/en-US/adodotnetentityframework/ Ознакомьтесь с PLINQO — набором шаблонов CodeSmith — plinqo.com — очень хорошо сделано, позволяет обновлять вашу модель из базы данных и создает один файл кода для каждого класса объектов. - person User; 19.07.2012