question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

A question regarding use cases and database transactions

See original GitHub issue

I’m sorry if this isn’t the right place to ask such a question, I’ve searched for hours everywhere and cannot seem to find an answer.

If i have a use case that fetches a two aggregates of different types from their repositories, and passes them to a domain service that preforms business logic on the aggregates and returns them to the use case, how would i save all the aggregates back to the database in a single transaction ?.

one solution i came up with is to have one of the repositories methods take the second aggregate as an argument to include in the database transaction:

interface IMemberRepo {
  upgradeMemberToGold: (member: Member, payment: Payment) => Promise<void>
}

// or
interface IPaymentRepo {
  markPaymentAsFulfilled: (payment: Payment, member: Member) => Promise<void>
}

if a member aggregate gets upgraded to gold there must be a payment aggregate with fulfilled: true that exists, the above solution works but I’m not sure if it 100% adheres to DDD principles.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
Sairysscommented, Sep 19, 2021

Here is my implementation:

  • unit-of-work-orm.ts - base class to work with TypeOrm Repositories
  • unit-of-work.ts - this is a class to convert TypeOrm repositories to Domain Repositories
  • create-user.service.ts - here you get the repository that you need and then wrap an execution in a this.unitOfWork.execute

Edit: UnitOfWork refactored to support correlationId. This is needed to use different query runners for each request, otherwise query fails if there is a lot of concurrent requests since before they all used the same connection pool.

1reaction
Sairysscommented, Sep 14, 2021

There can be multiple ways of implementing it depending on your database sdk/orm. I’d try to do it as generic as possible to be able to reuse it:

interface IUnitOfWork {
  add<T extends Entity>(entities: T[]): Promise<void>
  commit(): Promise<void>
  abort(): Promise<void>
}

With add() method you can add any amount of entities at any point, put them somewhere in an array internally, and then when you call commit() it just saves everything at once.

Edit: sorry, the solution above is based on my other project which uses Event Sourcing and there is no need to include reads in the transaction there so it will not work for you I guess 😃 if you want to include reads in the transaction, returning repositories seems like a good solution

Read more comments on GitHub >

github_iconTop Results From Across the Web

Top 50+ Database Interview Questions and Answers
Q #1) What do you understand by 'Database'? Answer: Database is an organized collection of related data where the data is stored and...
Read more >
How to Decide to use Database Transactions - Stack Overflow
A transaction should be used when you need a set of changes to be processed completely to consider the operation complete and valid....
Read more >
Understanding Transactional Database: 5 Important Points
One of the key advantages of using a transaction is that it will keep the data stable, regardless of whether it succeeds or...
Read more >
What is a database transaction? - Fauna
A database transaction is a sequence of multiple operations performed on a database, and all served as a single logical unit of work ......
Read more >
SQL Server Transaction Log Interview Questions - SQLShack
In this article, we will discuss a number of important SQL Server Transaction Log interview questions that you may be asked during a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found