diff --git a/Controllers/AppUsersController.cs b/Controllers/AppUsersController.cs index d6bbc2b..42c9104 100644 --- a/Controllers/AppUsersController.cs +++ b/Controllers/AppUsersController.cs @@ -14,31 +14,29 @@ namespace TicketManager.Controllers [ApiController] public class UsersController : ControllerBase { - private readonly AppDbContext _context; + private readonly IAppUserRepository _users; - public UsersController(AppDbContext context) + public UsersController(IAppUserRepository users) { - _context = context; + _users = users; } // GET: api/Users [HttpGet] - public async Task>> GetUsers() + public async Task> GetUsers() { - return await getAllAppUsersAsync(); + return await _users.List(); } // GET: api/Users/5 [HttpGet("{id}")] public async Task> GetUser(Guid id) { - var user = await getAppUserByIdAsync(id); - + var user = await _users.GetUser(id); if (user == null) { return NotFound(); } - return user; } @@ -52,16 +50,13 @@ namespace TicketManager.Controllers { return BadRequest(); } - - _context.Entry(user).State = EntityState.Modified; - try { - await _context.SaveChangesAsync(); + await _users.Update(user); } catch (DbUpdateConcurrencyException) { - if (!UserExists(id)) + if (!_users.Exists(id)) { return NotFound(); } @@ -70,7 +65,6 @@ namespace TicketManager.Controllers throw; } } - return NoContent(); } @@ -80,32 +74,27 @@ namespace TicketManager.Controllers [HttpPost] public async Task> PostUser(AppUser user) { - _context.AppUsers.Add(user); - await _context.SaveChangesAsync(); - + await _users.Add(user); return CreatedAtAction("GetUser", new { id = user.Id }, user); } // DELETE: api/Users/5 [HttpDelete("{id}")] - public async Task> DeleteUser(int id) + public async Task> DeleteUser(Guid id) { - var user = await _context.AppUsers.FindAsync(id); + var user = await _users.GetUser(id); if (user == null) { return NotFound(); } - - _context.AppUsers.Remove(user); - await _context.SaveChangesAsync(); - + await _users.Delete(user); return user; } [HttpGet("{id}/projects")] public async Task>> GetAppUserProjects(Guid id) { - AppUser user = await getAppUserByIdAsync(id); + AppUser user = await _users.GetUser(id); if (user == null) { return BadRequest(); @@ -116,36 +105,12 @@ namespace TicketManager.Controllers [HttpGet("{id}/tickets/")] public async Task>> GetAppUserTickets(Guid id) { - AppUser user = await getAppUserByIdAsync(id); + AppUser user = await _users.GetUser(id); if (user == null) { return BadRequest(); } return user.GetTickets(); } - - private bool UserExists(Guid id) - { - return _context.AppUsers.Any(e => e.Id == id); - } - - private IQueryable appUserQuery() - { - return _context.AppUsers - .Include(p => p.Assignments) - .ThenInclude(a => a.Project) - .ThenInclude(p => p.Tickets) - .Include(p => p.Edits); - } - - private async Task>> getAllAppUsersAsync() - { - return await appUserQuery().ToListAsync(); - } - - private async Task getAppUserByIdAsync(Guid id) - { - return await appUserQuery().FirstOrDefaultAsync(a => a.Id == id); - } } } diff --git a/Controllers/ProjectsController.cs b/Controllers/ProjectsController.cs index 8091d06..18c6de9 100644 --- a/Controllers/ProjectsController.cs +++ b/Controllers/ProjectsController.cs @@ -13,10 +13,10 @@ namespace TicketManager.Controllers [ApiController] public class ProjectsController : ControllerBase { - private AppDbContext _dbContext; - public ProjectsController(AppDbContext context) + private IProjectRepository _projects; + public ProjectsController(IProjectRepository context) { - _dbContext = context; + _projects = context; } /// @@ -33,8 +33,7 @@ namespace TicketManager.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetProjects() { - UnitOfWork _context = new UnitOfWork(_dbContext); - return await _context.Projects.List(); + return await _projects.List(); } /// @@ -53,8 +52,7 @@ namespace TicketManager.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> GetProject(int id) { - UnitOfWork _context = new UnitOfWork(_dbContext); - Project project = await _context.Projects.Get(id); + Project project = await _projects.Get(id); if (project == null) { return NotFound(); } return project; } @@ -83,16 +81,14 @@ namespace TicketManager.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task PutProject(int id, Project project) { - UnitOfWork _context = new UnitOfWork(_dbContext); if (id != project.Id) { return BadRequest(); } try { - _context.Projects.Update(project); - await _context.Complete(); + await _projects.Update(project); } catch (DbUpdateConcurrencyException) { - if (!_context.Projects.Exists(id)) { return NotFound(); } + if (!_projects.Exists(id)) { return NotFound(); } else { throw; } } return NoContent(); @@ -120,10 +116,8 @@ namespace TicketManager.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> PostProject(Project project) { - UnitOfWork _context = new UnitOfWork(_dbContext); if (!ModelState.IsValid) { return BadRequest(); } - _context.Projects.Add(project); - await _context.Complete(); + await _projects.Add(project); return CreatedAtAction("GetProject", new { id = project.Id }, project); } @@ -142,14 +136,12 @@ namespace TicketManager.Controllers [HttpDelete("{id}")] public async Task DeleteProject(int id) { - UnitOfWork _context = new UnitOfWork(_dbContext); - var project = await _context.Projects.Get(id); + var project = await _projects.Get(id); if (project == null) { return NotFound(); } - _context.Projects.Delete(project); - await _context.Complete(); + await _projects.Delete(project); return Ok(); } @@ -168,8 +160,7 @@ namespace TicketManager.Controllers [HttpGet("{id}/members")] public async Task>> GetProjectMembers(int id) { - UnitOfWork _context = new UnitOfWork(_dbContext); - Project project = await _context.Projects.Get(id); + var project = await _projects.Get(id); if (project == null) { return NotFound(); } return project.GetMembers(); @@ -198,8 +189,7 @@ namespace TicketManager.Controllers [HttpPut("{id}/members")] public async Task> SetProjectMembers(int id, List projectMembers) { - UnitOfWork _context = new UnitOfWork(_dbContext); - Project project = await _context.Projects.Get(id); + Project project = await _projects.Get(id); if (project == null) { return NotFound(); @@ -207,8 +197,7 @@ namespace TicketManager.Controllers project.SetMembers(projectMembers); try { - _context.Projects.Update(project); - await _context.Complete(); + await _projects.Update(project); } catch (DbUpdateException /* ex */) { diff --git a/Controllers/ProjectsController_working.cs b/Controllers/ProjectsController_working.cs deleted file mode 100644 index 3936677..0000000 --- a/Controllers/ProjectsController_working.cs +++ /dev/null @@ -1,317 +0,0 @@ -// using System; -// using System.Collections.Generic; -// using System.Linq; -// using System.Net.Mime; -// using System.Threading.Tasks; -// using Microsoft.AspNetCore.Http; -// using Microsoft.AspNetCore.Mvc; -// using Microsoft.EntityFrameworkCore; -// using TicketManager.Data; -// using TicketManager.Models; - - -// namespace TicketManager.Controllers -// { -// [Produces("application/json")] -// [Route("api/v1/[controller]")] -// [ApiController] -// public class ProjectsController : ControllerBase -// { -// private readonly IProjectRepository _projectRepo; - -// public ProjectsController(IProjectRepository projectRepo) -// { -// _projectRepo = projectRepo; -// } - -// /// -// /// Returns all existing projects. -// /// -// /// -// /// Sample request: -// /// -// /// GET: api/Projects -// /// -// /// -// /// Returns all existing projects -// [HttpGet] -// [ProducesResponseType(StatusCodes.Status200OK)] -// public async Task> GetProjects() -// { -// return await _projectRepo.ListAsync(); -// // GetAllProjectsAsync(); -// } - -// /// -// /// Returns a specific project. -// /// -// /// -// /// Sample request: -// /// -// /// GET: api/Projects/2 -// /// -// /// -// /// Returns a specific project -// /// If the required project is null -// [HttpGet("{id}")] -// [ProducesResponseType(StatusCodes.Status200OK)] -// [ProducesResponseType(StatusCodes.Status404NotFound)] -// public async Task> GetProject(int id) -// { -// Project project = await _projectRepo.GetByIdAsync(id); -// if (project == null) { return NotFound(); } -// return project; -// } - -// /// -// /// Updates a specific project. -// /// -// /// -// /// Sample request: -// /// -// /// PUT: api/Projects/3 -// /// { -// /// "id": "357727fd-5262-4522-b8a3-38271d43de84", -// /// "firstName": "Thomas", -// /// "lastName": "Price", -// /// "presentation": "New Team?!", -// /// "email": "tp@mail.com", -// /// "phone": "0198237645" -// /// } -// /// -// /// -// /// Returns the modified project -// /// Request was succesful but no content is changed -// /// If the required project is null -// [HttpPut("{id}")] -// [ProducesResponseType(StatusCodes.Status200OK)] -// [ProducesResponseType(StatusCodes.Status204NoContent)] -// [ProducesResponseType(StatusCodes.Status404NotFound)] -// public async Task PutProject(int id, Project project) -// { -// if (id != project.Id) { return BadRequest(); } - -// try -// { -// await _projectRepo.UpdateAsync(project); -// } -// catch (DbUpdateConcurrencyException) -// { -// if (!_projectRepo.Exists(id)) -// { -// return NotFound(); -// } -// else -// { -// throw; -// } -// } - -// return NoContent(); -// } - -// /// -// /// Creates a project. -// /// -// /// -// /// Sample request: -// /// -// /// POST: api/Projects/ -// /// { -// /// "firstName": "Thomas", -// /// "lastName": "Price", -// /// "presentation": "New Team?!", -// /// "email": "tp@mail.com", -// /// "phone": "0198237645" -// /// } -// /// -// /// -// /// Returns the created project -// [HttpPost] -// [ProducesResponseType(StatusCodes.Status201Created)] -// [ProducesResponseType(StatusCodes.Status404NotFound)] -// public async Task> PostProject(Project project) -// { -// if (!ModelState.IsValid) { return BadRequest(); } -// await _projectRepo.AddAsync(project); - -// return CreatedAtAction("GetProject", new { id = project.Id }, project); -// } - - - - -// /// -// /// Deletes a project. -// /// -// /// -// /// Sample request: -// /// -// /// DELETE: api/Projects/5 -// /// -// /// -// /// Returns the deleted project -// [ProducesResponseType(StatusCodes.Status200OK)] -// [ProducesResponseType(StatusCodes.Status404NotFound)] -// [HttpDelete("{id}")] -// public async Task> DeleteProject(int id) -// { -// var project = await _projectRepo.GetByIdAsync(id); -// if (project == null) -// { -// return NotFound(); -// } -// await _projectRepo.DeleteAsync(id); -// return project; -// } - -// /// -// /// Gets a project members. -// /// -// /// -// /// Sample request: -// /// -// /// GET: api/Projects/5/Members -// /// -// /// -// /// Returns the project members -// [ProducesResponseType(StatusCodes.Status200OK)] -// [ProducesResponseType(StatusCodes.Status404NotFound)] -// [HttpGet("{id}/members")] -// public async Task>> GetProjectMembers(int id) -// { -// Project project = await _projectRepo.GetByIdAsync(id); -// if (project == null) -// { return NotFound(); } -// return project.GetMembers(); -// } - -// /// -// /// Updates a project members. -// /// -// /// -// /// Sample request: -// /// -// /// PUT: api/Projects/5/Members -// /// { -// /// "id": "357727fd-5262-4522-b8a3-38271d43de84", -// /// "firstName": "Thomas", -// /// "lastName": "Price", -// /// "presentation": "New Team?!", -// /// "email": "tp@mail.com", -// /// "phone": "0198237645" -// /// } -// /// -// /// No content -// [ProducesResponseType(StatusCodes.Status204NoContent)] -// [ProducesResponseType(StatusCodes.Status404NotFound)] -// [HttpPut("{id}/members")] -// public async Task> SetProjectMembers(int id, List projectMembers) -// { -// Project project = await _projectRepo.GetByIdAsync(id); -// if (project == null) -// { -// return NotFound(); -// } -// project.SetMembers(projectMembers); -// try -// { -// await _projectRepo.UpdateAsync(project); -// } -// catch (DbUpdateException /* ex */) -// { -// //Log the error (uncomment ex variable name and write a log.) -// ModelState.AddModelError("", "Unable to save changes. " + -// "Try again, and if the problem persists, " + -// "see your system administrator."); -// } -// return NoContent(); -// } - -// // /// -// // /// Assign a user to a project. -// // /// -// // /// -// // /// Sample request: -// // /// -// // /// POST: api/Projects/addmembers -// // /// [{ -// // /// "id": "357727fd-5262-4522-b8a3-38271d43de84", -// // /// "firstName": "Thomas", -// // /// "lastName": "Price", -// // /// "presentation": "New Team?!", -// // /// "email": "tp@mail.com", -// // /// "phone": "0198237645" -// // /// }] -// // /// -// // /// -// // /// Returns the created project -// // [ProducesResponseType(StatusCodes.Status204NoContent)] -// // [ProducesResponseType(StatusCodes.Status404NotFound)] -// // [HttpPut("{id}/addMembers")] -// // public async Task> AddMembersToProject(int id, List usersToAdd) -// // { -// // if (usersToAdd == null) -// // { -// // return BadRequest(); -// // } -// // Project project = await GetProjectByIdAsync(id); -// // project.AddMembers(usersToAdd); -// // try -// // { -// // await _context.SaveChangesAsync(); -// // } -// // catch (DbUpdateException /* ex */) -// // { -// // //Log the error (uncomment ex variable name and write a log.) -// // ModelState.AddModelError("", "Unable to save changes. " + -// // "Try again, and if the problem persists, " + -// // "see your system administrator."); -// // } -// // return NoContent(); -// // } - -// // /// -// // /// Remove a user to a project. -// // /// -// // /// -// // /// Sample request: -// // /// -// // /// PUT: api/Projects/removemembers -// // /// [{ -// // /// "id": "357727fd-5262-4522-b8a3-38271d43de84", -// // /// "firstName": "Thomas", -// // /// "lastName": "Price", -// // /// "presentation": "New Team?!", -// // /// "email": "tp@mail.com", -// // /// "phone": "0198237645" -// // /// }] -// // /// -// // /// -// // /// Returns the created project -// // [ProducesResponseType(StatusCodes.Status204NoContent)] -// // [ProducesResponseType(StatusCodes.Status404NotFound)] -// // [HttpPut("{id}/removeMembers")] -// // public async Task> RemoveMembersFromProject(int id, List usersToRemove) -// // { -// // Project project = await GetProjectByIdAsync(id); -// // project.RemoveMembers(usersToRemove); -// // try -// // { -// // await _context.SaveChangesAsync(); -// // } -// // catch (DbUpdateException /* ex */) -// // { -// // //Log the error (uncomment ex variable name and write a log.) -// // ModelState.AddModelError("", "Unable to save changes. " + -// // "Try again, and if the problem persists, " + -// // "see your system administrator."); -// // } -// // return NoContent(); -// // } - - - - -// } -// } diff --git a/Controllers/TicketsController.cs b/Controllers/TicketsController.cs index 17dac2c..5c9cd37 100644 --- a/Controllers/TicketsController.cs +++ b/Controllers/TicketsController.cs @@ -14,31 +14,29 @@ namespace TicketManager.Controllers [ApiController] public class TicketsController : ControllerBase { - private readonly AppDbContext _context; + private readonly ITicketRepository _tickets; - public TicketsController(AppDbContext context) + public TicketsController(ITicketRepository tickets) { - _context = context; + _tickets = tickets; } // GET: api/Tickets [HttpGet] - public async Task>> GetTickets() + public async Task> GetTickets() { - return await getAllTicketsAsync(); + return await _tickets.List(); } // GET: api/Tickets/5 [HttpGet("{id}")] public async Task> GetTicket(int id) { - var ticket = await getTicketByIdAsync(id); - + var ticket = await _tickets.Get(id); if (ticket == null) { return NotFound(); } - return ticket; } @@ -52,16 +50,13 @@ namespace TicketManager.Controllers { return BadRequest(); } - - _context.Entry(ticket).State = EntityState.Modified; - try { - await _context.SaveChangesAsync(); + await _tickets.Update(ticket); } catch (DbUpdateConcurrencyException) { - if (!TicketExists(id)) + if (!_tickets.Exists(id)) { return NotFound(); } @@ -70,7 +65,6 @@ namespace TicketManager.Controllers throw; } } - return NoContent(); } @@ -80,9 +74,7 @@ namespace TicketManager.Controllers [HttpPost] public async Task> PostTicket(Ticket ticket) { - _context.Tickets.Add(ticket); - await _context.SaveChangesAsync(); - + await _tickets.Add(ticket); return CreatedAtAction("GetTicket", new { id = ticket.Id }, ticket); } @@ -90,59 +82,28 @@ namespace TicketManager.Controllers [HttpDelete("{id}")] public async Task> DeleteTicket(int id) { - var ticket = await _context.Tickets.FindAsync(id); + var ticket = await _tickets.Get(id); if (ticket == null) { return NotFound(); } - - _context.Tickets.Remove(ticket); - await _context.SaveChangesAsync(); - + await _tickets.Delete(ticket); return ticket; } [HttpGet("{id}/assignees")] public async Task>> GetTicketAssignees(int id) { - Ticket ticket = await getTicketByIdAsync(id); + Ticket ticket = await _tickets.Get(id); return ticket.GetAssignees(); } [HttpPut("{id}/closed")] - public async Task CloseTicket(int id) + public async Task CloseTicket(int id) { - Ticket ticket = await getTicketByIdAsync(id); + Ticket ticket = await _tickets.Get(id); ticket.Close(); - return NoContent(); - } - - private bool TicketExists(int id) - { - return _context.Tickets.Any(e => e.Id == id); - } - - private IQueryable ticketQuery() // problem with link - { - return _context.Tickets - .Include(p => p.Project) - .ThenInclude(a => a.Assignments) - .ThenInclude(p => p.User) - // .Include(p => p.Edits) - // .Include(p => p.Notes) - // .Include(p => p.Files) - // .Include(p => p.Creator) - ; - } - - private async Task>> getAllTicketsAsync() - { - return await ticketQuery().ToListAsync(); - } - - private async Task getTicketByIdAsync(int id) - { - return await ticketQuery().FirstOrDefaultAsync(a => a.Id == id); + return await PutTicket(ticket.Id, ticket); } } } diff --git a/Data/AppUserRepository.cs b/Data/AppUserRepository.cs new file mode 100644 index 0000000..a281ec8 --- /dev/null +++ b/Data/AppUserRepository.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using TicketManager.Models; +using System.Linq; +using System; +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; + +namespace TicketManager.Data +{ + public class AppUserRepository : GenericRepository, IAppUserRepository + { + private readonly IQueryable _query; + public AppUserRepository(AppDbContext context) : base(context) + { + _query = _dbSet + .Include(p => p.Assignments) + .ThenInclude(a => a.Project) + .ThenInclude(p => p.Tickets) + .Include(p => p.Edits) + .AsNoTracking(); + } + + public async Task GetUser(Guid id) + { + return await _query.FirstOrDefaultAsync(p => p.Id == id); + } + + public override async Task> List() + { + return await _query.ToListAsync(); + } + + public bool Exists(Guid id) + { + return _dbSet.Any(e => e.Id == id); + } + } +} \ No newline at end of file diff --git a/Data/GenericRepository.cs b/Data/GenericRepository.cs index ac7d4e8..1a90aa1 100644 --- a/Data/GenericRepository.cs +++ b/Data/GenericRepository.cs @@ -17,16 +17,18 @@ namespace TicketManager.Data _dbSet = _context.Set(); } - public void Add(T entity) + public async Task Add(T entity) { _dbSet.Add(entity); + return await _context.SaveChangesAsync(); } - public void Delete(T entity) + public async Task Delete(T entity) { if (_context.Entry(entity).State == EntityState.Detached) { _dbSet.Attach(entity); } _dbSet.Remove(entity); + return await _context.SaveChangesAsync(); } public async Task> Find(int id, Expression> expr) @@ -43,10 +45,11 @@ namespace TicketManager.Data return await _dbSet.AsNoTracking().ToListAsync(); } - public void Update(T entity) + public async Task Update(T entity) { _dbSet.Attach(entity); _context.Entry(entity).State = EntityState.Modified; + return await _context.SaveChangesAsync(); } } } \ No newline at end of file diff --git a/Data/Interfaces/IAppUserRepository.cs b/Data/Interfaces/IAppUserRepository.cs new file mode 100644 index 0000000..ab57db3 --- /dev/null +++ b/Data/Interfaces/IAppUserRepository.cs @@ -0,0 +1,12 @@ +using System; +using System.Threading.Tasks; +using TicketManager.Models; + +namespace TicketManager.Data +{ + public interface IAppUserRepository : IGenericRepository + { + Task GetUser(Guid id); + bool Exists(Guid id); + } +} \ No newline at end of file diff --git a/Data/Interfaces/IGenericRepository.cs b/Data/Interfaces/IGenericRepository.cs index e8594d8..915ef12 100644 --- a/Data/Interfaces/IGenericRepository.cs +++ b/Data/Interfaces/IGenericRepository.cs @@ -11,10 +11,10 @@ namespace TicketManager.Data Task Get(int id); Task> Find(int id, Expression> expr); - void Add(T entity); + Task Add(T entity); - void Update(T entity); + Task Update(T entity); - void Delete(T entity); + Task Delete(T entity); } } \ No newline at end of file diff --git a/Data/Interfaces/ITicketRepository.cs b/Data/Interfaces/ITicketRepository.cs new file mode 100644 index 0000000..de8af26 --- /dev/null +++ b/Data/Interfaces/ITicketRepository.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using TicketManager.Models; + +namespace TicketManager.Data +{ + public interface ITicketRepository : IGenericRepository + { + bool Exists(int id); + } +} \ No newline at end of file diff --git a/Data/Interfaces/IUnitOfWork.cs b/Data/Interfaces/IUnitOfWork.cs index 6a614f3..eab4e21 100644 --- a/Data/Interfaces/IUnitOfWork.cs +++ b/Data/Interfaces/IUnitOfWork.cs @@ -6,6 +6,8 @@ namespace TicketManager.Data public interface IUnitOfWork : IDisposable { IProjectRepository Projects { get; } + IAppUserRepository AppUsers { get; } + ITicketRepository Tickets { get; } Task Complete(); } } \ No newline at end of file diff --git a/Data/ProjectRepository.cs b/Data/ProjectRepository.cs index 7349bfd..675fe9c 100644 --- a/Data/ProjectRepository.cs +++ b/Data/ProjectRepository.cs @@ -30,7 +30,9 @@ namespace TicketManager.Data } public bool Exists(int id) - { return _dbSet.Any(e => e.Id == id); } + { + return _dbSet.Any(e => e.Id == id); + } public async Task> GetMembers(int id) { diff --git a/Data/TicketRepository.cs b/Data/TicketRepository.cs new file mode 100644 index 0000000..272adda --- /dev/null +++ b/Data/TicketRepository.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using TicketManager.Models; +using Microsoft.EntityFrameworkCore; + +namespace TicketManager.Data +{ + public class TicketRepository : GenericRepository, ITicketRepository + { + private IQueryable _query; + public TicketRepository(AppDbContext context) : base(context) + { + _query = _dbSet + .Include(p => p.Project) + .ThenInclude(a => a.Assignments) + .ThenInclude(p => p.User) + // .Include(p => p.Edits) + // .Include(p => p.Notes) + // .Include(p => p.Files) + // .Include(p => p.Creator) + .AsNoTracking(); + } + + public override async Task Get(int id) + { + return await _query.FirstOrDefaultAsync(p => p.Id == id); + } + + public override async Task> List() + { + return await _query.ToListAsync(); + } + + public bool Exists(int id) + { + return _dbSet.Any(e => e.Id == id); + } + } +} \ No newline at end of file diff --git a/Data/UnitOfWork.cs b/Data/UnitOfWork.cs index ad82b8b..3a70423 100644 --- a/Data/UnitOfWork.cs +++ b/Data/UnitOfWork.cs @@ -10,10 +10,16 @@ namespace TicketManager.Data { _context = context; Projects = new ProjectRepository(_context); + Tickets = new TicketRepository(_context); + AppUsers = new AppUserRepository(_context); } public IProjectRepository Projects { get; private set; } + public IAppUserRepository AppUsers { get; private set; } + + public ITicketRepository Tickets { get; private set; } + public async Task Complete() { return await _context.SaveChangesAsync();