Let's suppose I have 2 repositories
:
- first is responsible for creating job and return
jobId
- second is responsible for creating log and take
jobId
as argument
My goal is to:
- save
Job
andLog
simultaneously - prevent situation when in case of error only
Job
would be saved withoutLog
What is the most recommended way to get desired result?
I prepared 3 cases which came to my mind but if you see better alternative please share it.
- option 1 (getting result and save changes in controller)
public class JobRepository : IJobRepository
{
private readonly Context _context;
public JobRepository(Context context)
{
_context = context;
}
public Guid CreateJob()
{
var job = new Job { Id = Guid.NewGuid() };
_context.Jobs.Add(job);
return job.Id;
}
}
// ...
public class LogRepository : ILogRepository
{
private readonly Context _context;
public LogRepository(Context context)
{
_context = context;
}
public void CreateLog(Guid id)
{
var log = new Log { Jobid = id };
_context.Logs.Add(log);
}
}
// ...
public class JobsController : Controller
{
private readonly Context _context;
private readonly IJobRepository _jobRepository;
private readonly ILogRepository _logRepository;
public JobsController(Context context, JobRepository jobRepository, ILogRepository logRepository)
{
_context = context;
_jobRepository = jobRepository;
_logRepository = logRepository
}
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create()
{
var id = _jobRepository.CreateJob();
_logRepository.CreateLog(id);
_context.SaveChanges();
return RedirectToAction("Index");
}
}
- option 2 (inject one repository into another)
public class JobRepository : IJobRepository
{
private readonly Context _context;
private readonly ILogRepository _logRepository;
public JobRepository(Context context, ILogRepository logRepository)
{
_context = context;
}
public void CreateJob()
{
var job = new Job { Id = Guid.NewGuid() };
_context.Jobs.Add(job);
_logRepository.CreateLog(job.Id);
_context.SaveChanges();
}
}
// ...
public class LogRepository : ILogRepository
{
private readonly Context _context;
public LogRepository(Context context)
{
_context = context;
}
public void CreateLog(Guid id)
{
var log = new Log { Jobid = id };
_context.Logs.Add(log);
}
}
// ...
public class JobsController : Controller
{
private readonly IJobRepository _jobRepository;
public JobsController(JobRepository jobRepository)
{
_jobRepository = jobRepository;
}
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create()
{
_jobRepository.CreateJob();
return RedirectToAction("Index");
}
}
- option 3 (do not use context in controller but declare
Save
method in each repo)
public class JobRepository : IJobRepository
{
private readonly Context _context;
public JobRepository(Context context)
{
_context = context;
}
public Guid CreateJob()
{
var job = new Job { Id = Guid.NewGuid() };
_context.Jobs.Add(job);
return job.Id;
}
public void Save()
{
_context.SaveChanges();
}
}
// ...
public class LogRepository : ILogRepository
{
private readonly Context _context;
public LogRepository(Context context)
{
_context = context;
}
public void CreateLog(Guid id)
{
var log = new Log { Jobid = id };
_context.Logs.Add(log);
}
public void Save()
{
_context.SaveChanges();
}
}
// ...
public class JobsController : Controller
{
private readonly IJobRepository _jobRepository;
private readonly ILogRepository _logRepository;
public JobsController(JobRepository jobRepository, ILogRepository logRepository)
{
_jobRepository = jobRepository;
_logRepository = logRepository
}
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create()
{
var id = _jobRepository.CreateJob();
_logRepository.CreateLog(id);
return RedirectToAction("Index");
}
}
```
save
command fails then the other is not rolled back. So both changes should be tackled under the same DbContext to be able to participate in a same transaction. \$\endgroup\$EF
asSaveChanges
exists inDbContext
, if that's true, then the best approach would be to overrideSaveChanges
to log entities changes. \$\endgroup\$