I use three layer and Unit of work Design pattern together but project have credential bug!
data Read from database but does not save in it.
Context Class Can't get changes and CurrentTransaction
is null.
How can I fix this bug?
In this project I have three layer and one protocol for models
Data Code:
it layer have Context
and Repository
and IRepository
Repository class
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly FrontendContext context;
private readonly DbSet<TEntity> dbSet;
public Repository(){
context = new FrontendContext();
dbSet = context.Set<TEntity>();
}
public void Create (TEntity entity){
dbSet.Add(entity);
}
public IEnumerable<TEntity> GetAll(){
return dbSet.ToList();
}
}
IRepository interface
public interface IRepository<TEntity> where TEntity : class
{
public void Create (TEntity entity);
public IEnumerable<TEntity> GetAll();
}
Context class
public class FrontendContext : DbContext
{
public FrontendContext(): base(){}
protected override void OnConfiguring(DbContextOptionsBuilder builder){
builder.UseSqlServer(@"server=(local);Database=CredentialBug;Trusted_Connection=True;TrustServerCertificate=True");
}
public DbSet<Person> People { get; set; }
}
Services Code:
it have UnitOfWork
and IUnitOfWork
UnitOfWork class
public class UnitOfWork : IUnitOfWork
{
private readonly FrontendContext context;
public UnitOfWork(){
context = new FrontendContext();
}
public IRepository<TEntity> RepositoryBase<TEntity>() where TEntity : class {
return new Repository<TEntity>();
}
public void Commit() => context.SaveChanges();
}
IUnitOfWork interface
public interface IUnitOfWork
{
IRepository<TEntity> RepositoryBase<TEntity>() where TEntity : class ;
public void Commit();
}
Presentation Code
Add service to program file
builder.Services.AddTransient<IUnitOfWork, UnitOfWork>();
Now I use it in my Presentation like this :
Controller
public class HomeController : Controller
{
private readonly IUnitOfWork _UW;
public HomeController(IUnitOfWork UW)
{
_UW = UW;
}
public IActionResult Index()
{
IEnumerable<Person> people = _UW.RepositoryBase<Person>().GetAll();
return View(people);
}
public IActionResult Create(){
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Person model){
if (!ModelState.IsValid){
return View(model);
}
_UW.RepositoryBase<Person>().Create(model);
_UW.Commit();
return RedirectToAction(nameof(Index));
}
}
I test read data from database and correctly it work but add to database does not work correctly!!!
I found answer and share it.
its bug created when our sampling Context
class for each method. In this moment transaction
stay in the previous sample Context
and in Context
of new method transaction
is null, In result commit
method does not work.
we need some changes in this design pattern
Add Context
class to Constructor
like this
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly DbSet<TEntity> dbSet;
//get Context class from UnitOfWork Class
public Repository(FrontendContext context){
dbSet = context.Set<TEntity>();
}
public void Create (TEntity entity){
dbSet.Add(entity);
}
public IEnumerable<TEntity> GetAll(){
return dbSet.ToList();
}
}
once for all methods sample Context
class and send it to Repository
Class
public class UnitOfWork : IUnitOfWork
{
private readonly FrontendContext context;
public UnitOfWork(){
context = new FrontendContext();
}
public IRepository<TEntity> RepositoryBase<TEntity>() where TEntity : class {
return new Repository<TEntity>(context); //Send Context class to Repository
}
public void Commit() => context.SaveChanges();
}