Mi chiedo come combinare correttamente EF, Pattern di deposito e Unità di lavoro.
La soluzione che ho è del tutto corretta?
L'esempio qui sotto riguarda l'app Todo
ProjectController
public class ProjectController : Controller
{
private readonly IProjectService _pService; //it sholud be
public ProjectController(ProjectService pService)
{
_pService = pService;
}
[HttpGet]
public async Task<IActionResult> GetAsync()
{
var project = await _pService.GetAsync(1);
return Json(project);
}
}
ProjectService che ha una proprietà che è un UnitOfWork specifico.
public interface IProjectService
{
Task<Project> GetAsync(int id);
}
public class ProjectService : IProjectService
{
private readonly ITodoUnitOfWork _unitOfWork;
public ProjectService(ITodoUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public async Task<Project> GetAsync(int id)
{
var project = await _unitOfWork.Projects.GetAsync(id);
return project;
}
}
UnitOfWork
public interface ITodoUnitOfWork
{
IProjectRepository Projects { get; }
ITaskRepository Tasks { get; }
Task Complete();
}
public class UnitOfWork : ITodoUnitOfWork
{
private readonly DbContext _context;
public IProjectRepository Projects { get; protected set; }
public ITaskRepository Tasks { get; private set; }
public UnitOfWork(TodoContext todoContext, IProjectRepository projectRepository,
ITaskRepository taskRepository)
{
_context = todoContext;
Projects = projectRepository;
Tasks = taskRepository;
}
public async Task Complete()
{
await _context.SaveChangesAsync();
}
}
ProjectRepository
public interface IProjectRepository
{
//Minimal inteface
Task<Project> GetAsync(int id);
}
public class ProjectRepository : IProjectRepository
{
private readonly TodoContext _context;
public ProjectRepository(TodoContext context)
{
_context = context;
}
public async Task<Project> GetAsync(int id)
{
var project = _context.Projects
.Include(x => x.Tasks)
.FirstOrDefault(x => x.Id == id)
;
return await Task.FromResult(project);
}
}
TodoContext
public class TodoContext : DbContext
{
public DbSet<Tassk> Tasks { get; set; }
public DbSet<Project> Projects { get; set; }
public TodoContext(DbContextOptions options) : base(options)
{
}
}
Non preoccuparti delle interfacce minimaliste e che sono posizionate nei file di implementazione. È solo un esempio
Non ho un'interfaccia generica per il repository. È utile avere un'interfaccia generica che contenga solo i tipici metodi CRUD?
Quali DbSet devono essere inseriti nella classe che interpone DbContext?
Devo creare una classe DbContext e inserire tutti i DbSet, oppure dovrei creare un paio di classi di contesto?
Eg. in basso:
SingleContext
public class SingleContext : DbContext
{
public DbSet<Tassk> Tasks { get; set; }
public DbSet<Project> Projects { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<Setting> Settings { get; set; }
//etc....
}
Contesti multipli
UserContext
public class UserContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
//etc....
}
TodoContext
public class TodoContext : DbContext
{
public DbSet<Tassk> Tasks { get; set; }
public DbSet<Project> Projects { get; set; }
//etc....
}
Contesto applicazione
public class ApplicationContext : DbContext
{
public DbSet<Setting> Settings { get; set; }
//etc....
}