From b5eafb77ff38d7867acecc812d3d91c395782c5b Mon Sep 17 00:00:00 2001 From: Matej Hires Date: Tue, 2 Jan 2024 19:22:21 +0100 Subject: [PATCH] refactor: implemented unit of work --- .../Identity/Controllers/AccountController.cs | 13 ++-- .../Identity/Repositories/IUserRepository.cs | 14 ---- .../Identity/Repositories/UserRepository.cs | 73 ------------------- .../AutomatedTestingApp/Program.cs | 4 +- .../Repositories/IRepository.cs | 19 +++++ .../Repositories/IUnitOfWork.cs | 8 ++ .../Repositories/Repository.cs | 62 ++++++++++++++++ .../Repositories/UnitOfWork.cs | 39 ++++++++++ 8 files changed, 138 insertions(+), 94 deletions(-) delete mode 100644 AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/IUserRepository.cs delete mode 100644 AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/UserRepository.cs create mode 100644 AutomatedTestingApp/AutomatedTestingApp/Repositories/IRepository.cs create mode 100644 AutomatedTestingApp/AutomatedTestingApp/Repositories/IUnitOfWork.cs create mode 100644 AutomatedTestingApp/AutomatedTestingApp/Repositories/Repository.cs create mode 100644 AutomatedTestingApp/AutomatedTestingApp/Repositories/UnitOfWork.cs diff --git a/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Controllers/AccountController.cs b/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Controllers/AccountController.cs index 5138018..250897a 100644 --- a/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Controllers/AccountController.cs +++ b/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Controllers/AccountController.cs @@ -1,5 +1,6 @@ using System.Security.Claims; -using AutomatedTestingApp.Areas.Identity.Repositories; +using AutomatedTestingApp.Areas.Identity.Models; +using AutomatedTestingApp.Repositories; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc; @@ -8,11 +9,12 @@ namespace AutomatedTestingApp.Areas.Identity.Controllers; public class AccountController : Controller { - private readonly IUserRepository _userRepository; + private readonly IUnitOfWork _unitOfWork; + private IRepository UserRepository => _unitOfWork.GetRepository(); - public AccountController(IUserRepository userRepository) + public AccountController(IUnitOfWork unitOfWork) { - _userRepository = userRepository; + _unitOfWork = unitOfWork; } public IActionResult Login(string? returnUrl = null) @@ -24,7 +26,8 @@ public IActionResult Login(string? returnUrl = null) [HttpPost] public async Task Login(string userName, string password, string? returnUrl = null) { - var user = await _userRepository.GetUserByUsernameAsync(userName); + var user = UserRepository.Get(x => x.Username == userName).FirstOrDefault(); + if (user == null || user.Password != password) { ViewData["ReturnUrl"] = returnUrl; diff --git a/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/IUserRepository.cs b/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/IUserRepository.cs deleted file mode 100644 index 52a99c5..0000000 --- a/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/IUserRepository.cs +++ /dev/null @@ -1,14 +0,0 @@ -using AutomatedTestingApp.Areas.Identity.Models; - -namespace AutomatedTestingApp.Areas.Identity.Repositories; - -public interface IUserRepository -{ - IEnumerable GetUsers(); - IdentityUser? GetUserById(Guid userId); - Task GetUserByUsernameAsync(string username); - void CreateUser(IdentityUser user); - void UpdateUser(IdentityUser user); - void DeleteUser(IdentityUser user); - void Save(); -} \ No newline at end of file diff --git a/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/UserRepository.cs b/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/UserRepository.cs deleted file mode 100644 index 732f8d2..0000000 --- a/AutomatedTestingApp/AutomatedTestingApp/Areas/Identity/Repositories/UserRepository.cs +++ /dev/null @@ -1,73 +0,0 @@ -using AutomatedTestingApp.Areas.Identity.Models; -using AutomatedTestingApp.Helpers; -using Microsoft.EntityFrameworkCore; - -namespace AutomatedTestingApp.Areas.Identity.Repositories; - -public class UserRepository : IUserRepository, IDisposable -{ - private readonly DataContext _context; - - public UserRepository(DataContext context) - { - _context = context; - } - - public IEnumerable GetUsers() - { - return _context.Users.ToList(); - } - - public IdentityUser? GetUserById(Guid userId) - { - return _context.Users.FirstOrDefault(x => x.UserId == userId); - } - - public Task GetUserByUsernameAsync(string username) - { - return _context.Users.FirstOrDefaultAsync(x => x.Username == username); - } - - public void CreateUser(IdentityUser user) - { - _context.Users.Add(user); - } - - public void UpdateUser(IdentityUser user) - { - _context.Users.Update(user); - } - - public void DeleteUser(IdentityUser user) - { - var student = GetUserById(user.UserId); - - if(student != null) - _context.Users.Remove(student); - } - - public void Save() - { - _context.SaveChanges(); - } - - private bool _disposed; - - protected virtual void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - _context.Dispose(); - } - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } -} \ No newline at end of file diff --git a/AutomatedTestingApp/AutomatedTestingApp/Program.cs b/AutomatedTestingApp/AutomatedTestingApp/Program.cs index fc5db1c..eef1ef0 100644 --- a/AutomatedTestingApp/AutomatedTestingApp/Program.cs +++ b/AutomatedTestingApp/AutomatedTestingApp/Program.cs @@ -1,5 +1,5 @@ -using AutomatedTestingApp.Areas.Identity.Repositories; using AutomatedTestingApp.Helpers; +using AutomatedTestingApp.Repositories; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.EntityFrameworkCore; @@ -12,7 +12,7 @@ throw new InvalidOperationException("Connection string 'DefaultConnection' not found."); builder.Services.AddDbContext(options => options.UseSqlite($"DataSource={connectionString};Cache=Shared")); -builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(x => { diff --git a/AutomatedTestingApp/AutomatedTestingApp/Repositories/IRepository.cs b/AutomatedTestingApp/AutomatedTestingApp/Repositories/IRepository.cs new file mode 100644 index 0000000..68ed327 --- /dev/null +++ b/AutomatedTestingApp/AutomatedTestingApp/Repositories/IRepository.cs @@ -0,0 +1,19 @@ +using System.Linq.Expressions; + +namespace AutomatedTestingApp.Repositories; + +public interface IRepository +{ + IEnumerable Get(Expression>? filter = null, + Func, IOrderedQueryable>? orderBy = null); + + TEntity GetById(object id); + + void Insert(TEntity entity); + + void Update(TEntity entity); + + void Delete(object id); + + void Delete(TEntity entityToDelete); +} \ No newline at end of file diff --git a/AutomatedTestingApp/AutomatedTestingApp/Repositories/IUnitOfWork.cs b/AutomatedTestingApp/AutomatedTestingApp/Repositories/IUnitOfWork.cs new file mode 100644 index 0000000..7534f21 --- /dev/null +++ b/AutomatedTestingApp/AutomatedTestingApp/Repositories/IUnitOfWork.cs @@ -0,0 +1,8 @@ +namespace AutomatedTestingApp.Repositories; + +public interface IUnitOfWork +{ + void Commit(); + void Rollback(); + IRepository GetRepository() where TEntity : class; +} \ No newline at end of file diff --git a/AutomatedTestingApp/AutomatedTestingApp/Repositories/Repository.cs b/AutomatedTestingApp/AutomatedTestingApp/Repositories/Repository.cs new file mode 100644 index 0000000..2c310a5 --- /dev/null +++ b/AutomatedTestingApp/AutomatedTestingApp/Repositories/Repository.cs @@ -0,0 +1,62 @@ +using System.Linq.Expressions; +using AutomatedTestingApp.Helpers; +using Microsoft.EntityFrameworkCore; + +namespace AutomatedTestingApp.Repositories; + +public class Repository : IRepository where TEntity : class +{ + private readonly DbSet _dbSet; + + public Repository(DataContext context) + { + _dbSet = context.Set(); + } + + public IEnumerable Get(Expression>? filter = null, + Func, IOrderedQueryable>? orderBy = null) + { + IQueryable query = _dbSet; + + if (filter != null) + query = query.Where(filter); + + if (orderBy != null) + return orderBy(query).ToList(); + + return _dbSet.ToList(); + } + + public TEntity GetById(object id) + { + return _dbSet.Find(id); + } + + public void Insert(TEntity entity) + { + _dbSet.Add(entity); + } + + public void Update(TEntity entity) + { + _dbSet.Attach(entity); + } + + public void Delete(object id) + { + TEntity entityToDelete = _dbSet.Find(id); + + if (entityToDelete == null) + return; + + Delete(entityToDelete); + } + + public void Delete(TEntity entityToDelete) + { + if (_dbSet.Local.Contains(entityToDelete)) + _dbSet.Remove(entityToDelete); + else + _dbSet.Attach(entityToDelete); + } +} diff --git a/AutomatedTestingApp/AutomatedTestingApp/Repositories/UnitOfWork.cs b/AutomatedTestingApp/AutomatedTestingApp/Repositories/UnitOfWork.cs new file mode 100644 index 0000000..82d8e29 --- /dev/null +++ b/AutomatedTestingApp/AutomatedTestingApp/Repositories/UnitOfWork.cs @@ -0,0 +1,39 @@ +using AutomatedTestingApp.Helpers; + +namespace AutomatedTestingApp.Repositories; + +public class UnitOfWork : IUnitOfWork, IDisposable +{ + private readonly DataContext _context; + private Dictionary _repositories; + + public UnitOfWork(DataContext context) + { + _context = context; + _repositories = new Dictionary(); + } + + public void Commit() + { + _context.SaveChanges(); + } + + public void Rollback() + { + // TODO rollback changes here + } + + public IRepository GetRepository() where TEntity : class + { + if (_repositories.Keys.Contains(typeof(TEntity))) + return (IRepository)_repositories[typeof(TEntity)]; + var repository = new Repository(_context); + _repositories.Add(typeof(TEntity), repository); + return repository; + } + + public void Dispose() + { + _context.Dispose(); + } +} \ No newline at end of file