1

In DDD, the model has to implement only the bussiness logic, and it has not the responsability about another things, like persistance.

So I was thinking that perhaps is in the application layer a good place, because it is the layer who get data from the database with the repository, call the methods of the domain and persists the data. Something like that:

class MyApplicationService
{
    public void UpdateEntity()
    {
        long myActualVersion = Repository.GetActualVersion(EntityToUpdate.Id);
        EntityToUpdate.Update(data);
        Repository.IncrementVersion(EntityToUpdate.Id);
        //Do something to check if it will be update the expected version or not.
        Repository.Commit();
    }
}

But I was thinking that perhaps it belongs to the repository, something like that:

class Repository
{
    Update(paramEntityId, paramNewData)
    {
        ActualEntity = _conntext.Get(paramEntityId);
        ActualEntity.Update(paramNewData);
        _context.Commit();
    }
}

In this case, in the database I could have a row version and it will throw an exception that could be handle in the application layer and decide if retry or not, for example.

I am thinking that perhaps the second option it is better, because concurrency is a database concern, so perhaps it is better to handle in the repository, but I am not sure if perhaps it is better in the application layer, or there are another options.

Thanks.

6
  • Why do you think this is a DB concern? Why are you waiting until the end to make the execution fail? What if (on your way to the DB) you have performed operations that can not be undone or are not safe? How are you going to test concurrency control without a database? If concurrency control is among your requirements. Real, specific and well-defined requirements, then you have to prove it works with a test. You can not just say "it will work once in production with a real database". Delegating concurrency control to the DB is like delegating validations because constraints can do the job too.
    – Laiv
    Commented Oct 13, 2022 at 15:19
  • @Laiv Where would you put the concurrency control? Commented Oct 13, 2022 at 15:23
  • There are no silver bullets. It depends, a lot, on the requirements. That's why I made questions you should think about. And make your own questions based on your knowledge about the domain. If the concurrency is inherent to the domain, then why not in the domain layer? If not, well, it's likely to be an application concern. Isn't it? If you want it to be a business capability, something you can switch on and off, then the business layer seems more adequate.
    – Laiv
    Commented Oct 13, 2022 at 15:28
  • I am not sure if concurrency is inherent to domain. For example, the user name has to be unique in the system. No domain expert will tell how to manage that, if I have to use a property version in the user entity or not, or any other way. At domain level, from my point of view, the domain only has to ensure the user has a correct name (no empty, no only white space and another rules) but to ensure if it unique or not, it would have to access to the database, and for me it is a responsability outside the domain. Commented Oct 13, 2022 at 16:24
  • Suppose you are afraid of 2 requests competing for the same user name. Leave both to reach the DB. One of them will fail due to a UK constraint violation. Then you handle the error and ask the user to repeat with a different name because the one sent is already taken. Which user will get the error doesn't matter. You can not ensure that the first sending the request will win the race. There's a whole universe of things in-between the user's computer and the DB.
    – Laiv
    Commented Oct 14, 2022 at 14:14

1 Answer 1

1

The reference you should review is the original domain driven design book (Evans 2003). Chapter 6 describes life cycle management patterns (aggregates, factories, repositories).

Leave transaction control to the client. Although the REPOSITORY will insert into and delete from the database, it will ordinarily not commit anything.

Vaughn Vernon's 2013 book (Chapter 12) offers similar advice; transactions are managed in the application layer.

If you imagine that the application layer is managing a unit of work, then it makes sense that transaction management would be outside the repositories, since they should not know what other resources are also participating in the current transaction.

1
  • When you tell the transactions are managed in the application layer, do you mean that the domain entities can't have a version property for concurrency? I mean, where is implementing handle of conccurrency? Because in my case, the domain experts doesn't tell that an entity has to have a version number or what to do when conflicts happen, just tell, update enitty, create entity, do something, but they don't tell about concurrency. So it is why I was thinking if it is responsible of the repository (EF Core with a verison row, for example). Commented Oct 17, 2022 at 12:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.