Универсальный контроллер не выполняет метод CompleteOfWork Complete () - PullRequest
0 голосов
/ 17 сентября 2018

В ASP.NET MVC я создал универсальный контроллер для операций CRUD для базовых моделей.

Я передаю общий интерфейс хранилища контроллеру, а также интерфейс устройства. Я использую Ninject для внедрения зависимости от реализации.

Внедрение в репозиторий работает, например, действие Index работает и View отображается правильно, но когда программа достигает _unitOfWork.Complete (), ничего не происходит, и DB не обновляется.

Универсальный репозиторий и unitofwork работают в других случаях, когда я внедряю их в стандартные неуниверсальные контроллеры.

Что я делаю не так?

GenericController.cs

public class GenericController<TEntity> : Controller
    where TEntity : class

{
    private readonly IGenericRepository<TEntity> _repository;
    private readonly IUnitOfWork _unitOfWork;

    protected GenericController(IGenericRepository<TEntity> repository, IUnitOfWork unitOfWork)
    {
        _repository = repository;
        _unitOfWork = unitOfWork;
    }

    // GET: FileTypes
    public ActionResult Index()
    {
        return View(_repository.GetAll());
    }

    // GET: FileTypes/Create
    public ActionResult Create()
    {
        return View();
    }

    // POST: FileTypes/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Id,Name")] TEntity entity)
    {
        if (ModelState.IsValid)
        {
            _repository.Add(entity);
            _unitOfWork.Complete();
            return RedirectToAction("Index");
        }

        return View(entity);
    }

    // GET: FileTypes/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

        var entity = _repository.GetById(id);

        if (entity == null)
            return HttpNotFound();

        return View(entity);
    }

    // POST: FileTypes/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "Id,Name")] TEntity entity)
    {
        if (ModelState.IsValid)
        {
            _repository.Edit(entity);
            _unitOfWork.Complete();
            return RedirectToAction("Index");
        }
        return View(entity);
    }

    // POST: FileTypes/Delete/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = RoleName.Admin + ", " + RoleName.SuperAdmin)]
    public ActionResult Delete(int id)
    {
        try
        {
            _repository.Remove(_repository.GetById(id));
            _unitOfWork.Complete();
            return RedirectToAction("Index");
        }
        catch (Exception)
        {
            return new HttpStatusCodeResult(500);
        }

    }

}

Пример производного контроллера:

DisengagementReasonsController.cs

[Authorize(Roles = RoleName.SuperAdmin)]
public class DisengagementReasonsController : GenericController<DisengagementReason>
{
    public DisengagementReasonsController(IGenericRepository<DisengagementReason> repository, IUnitOfWork unitOfWork)
        : base(repository, unitOfWork)
    {

    }
}

IUnitOfWork.cs

public interface IUnitOfWork
{
    void Complete();
}

UnitOfWork.cs

public class UnitOfWork : IUnitOfWork
{
    private readonly MyAppDbContext _context;

    public UnitOfWork(MyAppDbContext context)
    {
        _context = context;
    }

    public void Complete()
    {
        _context.SaveChanges();
    }     
}

Ninject.Web.Common

public static class NinjectWebCommon
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start()
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
            RegisterServices(kernel);

            kernel.Bind(x =>
            {
                x.FromThisAssembly()
                    .SelectAllClasses()
                    .BindDefaultInterface();
            });

            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
    }
}

GenericRepository.cs

public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
    private readonly MyAppDbContext _context;
    private readonly DbSet<TEntity> _dbSet;

    public GenericRepository(MyAppDbContext context)
    {
        _context = context;
        _dbSet = context.Set<TEntity>();
    }

    public virtual IEnumerable<TEntity> GetAll()
    {
        return _dbSet.ToList();
    }

    public virtual TEntity GetById(object id)
    {
        return _dbSet.Find(id);
    }

    public virtual void Add(TEntity entity)
    {
        _dbSet.Add(entity);
    }

    public virtual void Edit(TEntity entityToUpdate)
    {
        _dbSet.Attach(entityToUpdate);
        _context.Entry(entityToUpdate).State = EntityState.Modified;
    }

    public virtual void Remove(object id)
    {
        var entityToDelete = _dbSet.Find(id);
        Remove(entityToDelete);
    }

    public virtual void Remove(TEntity entityToDelete)
    {
        if (_context.Entry(entityToDelete).State == EntityState.Detached)
        {
            _dbSet.Attach(entityToDelete);
        }
        _dbSet.Remove(entityToDelete);
    }
}

1 Ответ

0 голосов
/ 18 сентября 2018

Исходя из симптомов, наиболее вероятной причиной проблемы является то, что не один и тот же экземпляр DbContext внедряется в UoW и класс репозитория (возможно, из-за некоторой неправильной конфигурации DI).После некоторого обсуждения в комментариях выяснилось, что я сделал счастливый случай.:)

Однако, как примечание, я бы отметил, что DbContext EF реализует UoW и репозиторий сам по себе.В большинстве случаев реализация этих шаблонов поверх EF является просто ненужным чрезмерным усложнением, абстракцией абстракции.Я не рекомендую это без уважительной причины.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...