Внедрение схемы работы

Сначала создаю приложение с помощью кода структуры MVC MVC и Entity. Я использую репозиторий и шаблон работы с влиянием следующей ссылки.

http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

Здесь у меня есть вопрос о реализации Unit of Work в том, что ссылка на работу выполняется через прямое создание сущностей в самом классе.

public class UnitOfWork : IDisposable
{
    private SchoolContext context = new SchoolContext();
    private GenericRepository<Department> departmentRepository;

    public GenericRepository<Department> DepartmentRepository
    {
        get
        {

            if (this.departmentRepository == null)
            {
                this.departmentRepository = new GenericRepository<Department>(context);
            }
            return departmentRepository;
        }
    }

}

Считаете ли вы, что реализация достаточно хороша, потому что каждый раз, когда я добавляю/удаляю объекты, мне нужно изменить свою Единицу рабочего класса. Я считаю, что Единица работы не должна зависеть от организаций. Поскольку в моем приложении, основанном на отзывах Клиента, мы часто будем добавлять/удалять объекты.

Я могу казаться глупым, но дайте мне знать ваши взгляды на это.

Ответ 1

Шаблон "Единица работы" уже реализован в Entity Framework.

DbContext - это ваше подразделение работы. Каждый IDbSet является репозиторием.

using (var context = new SchoolContext())   // instantiate our Unit of Work
{
    var department = context.Departments.Find(id);
}

Ответ 2

Существует несколько разновидностей UnitOfWorkPattern. Тот, который вы описываете, - это показать все, есть и скрыть все. В подходе к скрытию единица работы ссылается на метод DbContext.SaveChanges() и ничего больше; звучит так, как вы хотите.

public YourContext : DbContext, IContext{}

public interface IUnitOfWork{
   void Commit();
}

public UnitOfWork : IUnitOfWork{
    private readonly IContext _context;

    //IOC should always inject the same instance of this, register it accordingly
    public UnitOfWork(IContext context){
        _context = context;
    }

    void Commit(){
           // try catch the validation exception if you want to return the validations this
           // way if your confident you've already validated you can put a void here or
           // return the intfrom save changes make sure you handle the disposing properly,
           // not going into that here you also may be doing other stuff here, have multiple
           // "contexts" to save in a single transaction or we have contextProcessors that
           // do stuff based on items in the context
          _context.SaveChanges();
   }
}

Это оставляет вопрос о том, как вы получаете свои репозитории в классы, которые им нужны, если вы не принимаете их из UnitOfWork. Это лучше всего использовать в рамках МОК. Опять здесь есть пара вариантов. Однажды зарегистрируйте UnitOfWork как один экземпляр для каждого запроса и внесите его в свой пользовательский класс репозитория.

public interface IRepository<T>
{
    IQueryable<T> Records();
    //other methods go here
}

public Repository : IRepository<T>
{
    private IContext _context;

    // same instance of context injected into the unit of work, this why when you Commit
    // everything will save, this can get tricky if you start adding Add, Update and stuff
    // but EF does have the support needed.
    public Repository(IContext context)
    {
       _context = context;
    }

    public Records()
    {
        return _context.Set<T>();
    }
}

public class SomeService : ISomeService{
   private readonly _myObjectRepository;

   public SomeService(IRepository<MyObject> myObjectRepository){
       _myObjectRepository = myObjectRepository;
   }
}

Лично я считаю IDbSet достаточной абстракцией, поэтому я больше не создаю репозитории. В чтобы ввести IDbSets из контекста, хотя вам необходимо зарегистрировать их как экземпляры, которые вы извлечение из контекста в настройке IOC. Это может быть сложным и зависит от ваших навыков может оказаться в ситуации, когда вам необходимо зарегистрировать каждый IDbSet, который, как я знаю, вы пытаетесь избежать.

Какая приятность в использовании IDbSet заключается в том, что у вас есть доступ к простым методам, например Add, и вы можете избежать некоторых более сложных частей работы с Entity и DbEntity в общем смысле.

public class SomeService : ISomeService {
    private readonly _myObjectSet;

    // requires specialized IOC configurations because you have to pull this instance from
    // the instance of the context, personally don't know how to do this with a single
    // registration so this has the same problem as having to add each new repository to the
    // unit of work.  In this case each new Entity I add to the context requires I add an IOC
    // registration for the type.

    public SomeService(IDbSet<MyObject> myObjectSet){
        _myObjectSet= myObjectSet;
    }
}

Ответ 3

Попробуйте передать SchoolContext в GenericRepository:

public GenericRepository<T>
{
    private SchoolContext _context;

    public GenericRepository(SchoolContext context)
    {
       _context = context;
    }

    public Get(int id)
    {
        return _context.Set<T>().Find(id);
    }
}

И используйте:

using(var context = new SchoolContext())
{
    var departmentRepository = new GenericRepository<Department>(context);
    var department = departmentRepository.Get(1);
}