DbContext should not leak to service layer. Service layer get data by calling repository in some in-memory objects. Then it perform the complex business logic on in-memory objects by calling some domain methods or perform itself. When the data is ready to store in external database then service layer again call repository to save the data.
Please find a sample code below.
Domain model:
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Name
{
get
{
return $"{FirstName} {LastName}";
}
}
public int Age { get; set; }
public bool? IsAdult { get; set; }
public void DetermineAdult()
{
if (Age >= 18) IsAdult = true;
else IsAdult = false;
}
}
User interface:
public IActionResult Index()
{
_userService.ProcessUsers();
return View();
}
Service layer:
// 1. Get data from repository in form of in-memory objects.
// 2. Perform some business logic with in-memory objects.
// 3. Send in-memory objects to repository to store in database.
void IUserService.ProcessUsers()
{
IEnumerable<User> users = _userRepository.GetAll();
foreach (User user in users)
{
user.DetermineAdult(); // Calling domain method to perform the business logic.
_userRepository.Update(user.Id, user);
}
}
Repository layer:
IEnumerable<User> IUserRepository.GetAll()
{
List<User> users = _userContext.Users.ToList();
return users;
}
void IUserRepository.Update(int userId, User user)
{
User userFromDb = _userContext.Users.FirstOrDefault(u => u.Id == userId);
if (userFromDb == null) return;
userFromDb.IsAdult = user.IsAdult;
_userContext.SaveChanges();
}
Solution structure
Please find the full code in my github repository
https://github.com/Arnab-Developer/OnionArchitecture
IQueryable
as abstraction type. Data access abstraction can have domain specific methods and types, then implementation of data access implementation will be responsible to convert database types into domain types. If you need complex query, you simply will add a another method. But try to keep as much logic in the service layer.