简体   繁体   English

使用 Unity 的 MVC 控制器构造函数注入中的工作单元和存储库模式不对数据库进行任何更改

[英]Unit of Work and Repository Pattern in MVC controller constructor injection using Unity not doing any changes to database

1.) I am a building new MVC application with 3 tier project architecture having: 1.) 我正在构建具有 3 层项目架构的新 MVC 应用程序,具有:

  1. Common Project with entities具有实体的公共项目
  2. Business/Service holding interfaces and logic classes and业务/服务持有接口和逻辑类和
  3. Data holding repositories, interfaces, DbContext and UnitOfWork classes.保存存储库、接口、 DbContextUnitOfWork类的数据。 I am using Unity Config to register dependencies, DbContext and UnitOfWork .我正在使用 Unity Config 来注册依赖项、 DbContextUnitOfWork

2.) I created a repository for each table and one generic repository that does basic CRUD operations. 2.) 我为每个表创建了一个存储库和一个执行基本 CRUD 操作的通用存储库。

Example Entity residing in Common Project:驻留在 Common Project 中的示例实体:

public class MenuSecd
{
    [Key, Column(Order = 0)]
    public string prg_module { get; set; }
    [Key, Column(Order = 1)]
    public int prg_numb { get; set; }
    [Key, Column(Order = 2)]
    public string menu_level { get; set; }
}

My generic Entity Logic Interface residing in Business Project:我驻留在业务项目中的通用实体逻辑接口:

public interface IEntityLogic<T> : ILogic where T : class
{
    void Create(T entity);
    void Delete(T entity);
    IEnumerable<T> GetAll();
    void Update(T entity);
}

Entity Logic Class:实体逻辑类:

public abstract class EntityLogic<T> : IEntityLogic<T> where T : class
{
    IUnitOfWork _unitOfWork;
    IGenericRepository<T> _repository;

    public EntityLogic(IUnitOfWork unitOfWork, IGenericRepository<T> repository)
    {
        _unitOfWork = unitOfWork;
        _repository = repository;
    }

    public virtual void Create(T entity)
    {
        if(entity == null)
        {
            throw new ArgumentNullException(nameof(entity));
        }

        _repository.Add(entity);
        _unitOfWork.Commit();
    }
}

Example Business Logic class for the entity defined in Common Project: Common Project 中定义的实体的示例业务逻辑类:

public class MenuSecdLogic : EntityLogic<MenuSecd>, IMenuSecdLogic
{
    IUnitOfWork _unitOfWork;
    IMenuSecdRepository _repository;
    public MenuSecdLogic(IUnitOfWork unitOfWork, IMenuSecdRepository repository) : base(unitOfWork, repository)
    {
        _unitOfWork = unitOfWork;
        _repository = repository;
    }

    public List<MenuSecd> GetItems(string usrgrp_id)
    {
        return _repository.GetItems(usrgrp_id);
    }
}

My Generic Repository in Data Project looks like:我在数据项目中的通用存储库如下所示:

public abstract class GenericRepository<T> : IGenericRepository<T> where T : class
{
    protected DbContext _entities;
    protected readonly IDbSet<T> _dbset;
    public GenericRepository(DbContext context)
    {
        _entities = context;
        _dbset = context.Set<T>();
    }
    public virtual T Add(T entity)
    {
        return _dbset.Add(entity);
    }

    public virtual T Delete(T entity)
    {
        return _dbset.Remove(entity);
    }

    public virtual void Edit(T entity)
    {
        _entities.Entry(entity).State = EntityState.Modified;
    }
}

Repository Interface for the same Entity is defined as:同一实体的存储库接口定义为:

public interface IMenuSecdRepository : IGenericRepository<MenuSecd>
{
    List<MenuSecd> GetItems(string usrgrp_id);
}

Repository class for above mentioned interface is:上述接口的存储库类是:

public class MenuSecdRepository : GenericRepository<MenuSecd>, IMenuSecdRepository
{
    public MenuSecdRepository(DbContext context) : base(context)
    {

    }

    public List<MenuSecd> GetItems(string usrgrp_id)
    {
        return _dbset.Where(m => m.usrgrp_id == usrgrp_id).ToList();
    }
}

My DbContext looks like:我的DbContext看起来像:

public class DashboardContext : DbContext
{
    public DashboardContext() : base("Name=DBEntities")
    {

    }

    public DbSet<MenuSecd> menusecd { get; set; }

    public override int SaveChanges()
    {
        var modifiedEntries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified);
        //future custom implementation like auditing
        return base.SaveChanges();
    }
}

My UnitOfWork looks like:我的 UnitOfWork 看起来像:

public sealed class UnitOfWork : IUnitOfWork
{
    private DbContext _dbContext;
    public UnitOfWork(DbContext context)
    {
        _dbContext = context;
    }

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

    //disposes current object
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    //disposes all external resources
    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_dbContext != null)
            {
                _dbContext.Dispose();
                _dbContext = null;
            }
        }
    }
}

My controller:我的控制器:

public class DashController : Controller
{
    private readonly IMenuSecdLogic _menuSecdLogic;
    public DashController(IMenuSecdLogic menuSecdLogic)
    {
         _menuSecdLogic = menuSecdLogic;          
    }
    public void Save()
    {
         var menuSecd = new menuSecd();
         //populate all fields for entity MenuSecd
         _menuSecdLogic.Create(menuSecd);
    }
}

My Unity Config in App_Start looks like :我在 App_Start 中的 Unity Config 如下所示:

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<DbContext, DashboardContext>();
    container.RegisterType<IUnitOfWork, UnitOfWork>();
    container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<>));
    container.RegisterType<IMenuSecdLogic, MenuSecdLogic>();
    container.RegisterType<IMenuSecdRepository, MenuSecdRepository>();
}

So when run above project everything builds fine.因此,当在项目上方运行时,一切都很好。 But when controller calls:但是当控制器调用时:

_menuSecdLogic.Create(menuSecd);

It reaches Entity Logic and adds a new entity to _repository at :它到达实体逻辑并在 _repository 添加一个新实体:

_repository.Add(entity);
_unitOfWork.Commit();

But when it hits next line to actually save it to database which is :但是当它到达下一行以实际将其保存到数据库时:

return _dbContext.SaveChanges();

in UnitOfWork.cs file.在 UnitOfWork.cs 文件中。 It comes to dashboardContext where it finally have to save it to database.它涉及到dashboardContext,它最终必须将其保存到数据库中。 But it does execute :但它确实执行:

var modifiedEntries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified);
    return base.SaveChanges();

But nothing changes in database.但数据库中没有任何变化。 There will be no record in database.数据库中将没有记录。 To test I have added modifiedEntries to see if it is in context or not.为了测试,我添加了 modifiedEntries 以查看它是否在上下文中。 By the time control reaches this point I see no modified entries at all.当控制到达这一点时,我根本看不到任何修改的条目。 But in EntityLogic.cs it does add a new entity to local entities in repository.但在EntityLogic.cs它确实向存储库中的本地实体添加了一个新实体。 I am not sure what is happening with UnitOfWork here.我不确定这里的 UnitOfWork 发生了什么。 I ran SQL Profiler to see if it is hitting database or not.我运行 SQL Profiler 以查看它是否正在访问数据库。 Interestingly it is not hitting database at all.有趣的是,它根本没有命中数据库。 But if my make following changes to EntityLogic like this:但是,如果我像这样对 EntityLogic 进行以下更改:

public virtual void Create(T entity)
{
    if(entity == null)
    {
        throw new ArgumentNullException(nameof(entity));
    }

    _repository.Add(entity);
    _repository.Save();
    //_unitOfWork.Commit();
}

It hits Database and records gets saved fine.它击中了数据库,记录保存得很好。 But I am not getting why it is neither tracking changes nor hitting database if I use _unitOfWork.Commit() which I want to do.但是我不明白为什么如果我使用我想做的_unitOfWork.Commit()它既不跟踪更改也不访问数据库。 Please help.请帮忙。

It looks like your issue is the scope of your DbContext .看起来您的问题是DbContext的范围。 Your UnitOfWork and GenericRepository<T> classes are getting different instances.您的UnitOfWorkGenericRepository<T>类正在获得不同的实例。

Not super familiar with Unity, but it looks like you want to use something like this for your DbContext registration:对 Unity 不是很熟悉,但看起来你想使用这样的东西DbContext注册DbContext

container.RegisterType<DbContext, DashboadContext>(new PerRequestLifetimeManager());

This will create a single DashboardContext for each request, and your UnitOfWork and GenericRepository<T> classes will be working within the same context.这将为每个请求创建一个DashboardContext ,并且您的UnitOfWorkGenericRepository<T>类将在相同的上下文中工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM