[英]Unit of Work and Repository Pattern in MVC controller constructor injection using Unity not doing any changes to database
1.) 我正在構建具有 3 層項目架構的新 MVC 應用程序,具有:
DbContext
和UnitOfWork
類的數據。 我正在使用 Unity Config 來注冊依賴項、 DbContext
和UnitOfWork
。2.) 我為每個表創建了一個存儲庫和一個執行基本 CRUD 操作的通用存儲庫。
駐留在 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; }
}
我駐留在業務項目中的通用實體邏輯接口:
public interface IEntityLogic<T> : ILogic where T : class
{
void Create(T entity);
void Delete(T entity);
IEnumerable<T> GetAll();
void Update(T entity);
}
實體邏輯類:
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();
}
}
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);
}
}
我在數據項目中的通用存儲庫如下所示:
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;
}
}
同一實體的存儲庫接口定義為:
public interface IMenuSecdRepository : IGenericRepository<MenuSecd>
{
List<MenuSecd> GetItems(string usrgrp_id);
}
上述接口的存儲庫類是:
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();
}
}
我的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();
}
}
我的 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;
}
}
}
}
我的控制器:
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);
}
}
我在 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>();
}
因此,當在項目上方運行時,一切都很好。 但是當控制器調用時:
_menuSecdLogic.Create(menuSecd);
它到達實體邏輯並在 _repository 添加一個新實體:
_repository.Add(entity);
_unitOfWork.Commit();
但是當它到達下一行以實際將其保存到數據庫時:
return _dbContext.SaveChanges();
在 UnitOfWork.cs 文件中。 它涉及到dashboardContext,它最終必須將其保存到數據庫中。 但它確實執行:
var modifiedEntries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified);
return base.SaveChanges();
但數據庫中沒有任何變化。 數據庫中將沒有記錄。 為了測試,我添加了 modifiedEntries 以查看它是否在上下文中。 當控制到達這一點時,我根本看不到任何修改的條目。 但在EntityLogic.cs
它確實向存儲庫中的本地實體添加了一個新實體。 我不確定這里的 UnitOfWork 發生了什么。 我運行 SQL Profiler 以查看它是否正在訪問數據庫。 有趣的是,它根本沒有命中數據庫。 但是,如果我像這樣對 EntityLogic 進行以下更改:
public virtual void Create(T entity)
{
if(entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
_repository.Add(entity);
_repository.Save();
//_unitOfWork.Commit();
}
它擊中了數據庫,記錄保存得很好。 但是我不明白為什么如果我使用我想做的_unitOfWork.Commit()
它既不跟蹤更改也不訪問數據庫。 請幫忙。
看起來您的問題是DbContext
的范圍。 您的UnitOfWork
和GenericRepository<T>
類正在獲得不同的實例。
對 Unity 不是很熟悉,但看起來你想使用這樣的東西DbContext
注冊DbContext
:
container.RegisterType<DbContext, DashboadContext>(new PerRequestLifetimeManager());
這將為每個請求創建一個DashboardContext
,並且您的UnitOfWork
和GenericRepository<T>
類將在相同的上下文中工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.