Since you are using Dapper (excellent choice!), you must be using a relational database. In this case, the very first step is to make sure you have appropriate foreign key relationships, including what to do un UPDATE and DELETE operations. Most RDBMS provide automatic cascading services on these operations. Set things up the way it makes sense to your project.
The next step is decide if your API will accept the full object graph or not. If you do, you have 2 options:
- Prepare CUD (create, update, delete) queries that fit exactly the graph you receive, including children, or children of children, etc.
- Internally do nesting calls that take care of child objects using the service objects of those child objects.
The first one is harder to program and maintain, but will be the most performant; the latter is the more maintainable, and should perform quite decently. Yes, I personally would go for #2.
The second option also has the advantage that you can easily provide API that can work at any level in the hierarchy.
Do I have an example of this? Unfortunately, no. Let's try to describe the process in a high-level way:
HTTP POST https://myapp.example.com/api/quotes
{
"id": 123,
"customerId": 453,
"products": [
{
"productId": 2342,
"quantity": 4.54,
},
{
...
}
]
}
The above would be the JSON representation of a quote. Internally, you accept this object. You realize there are several products in the quote that need insertion in the QuoteProducts
table, so you call the QuoteRepository
first, then add the parent ID to the products, then call the QuoteProductService
on each of the product associations, which in turn calls the QuoteProductRepository
to make the insertions.
The QuoteProductService
object would call other services if the product object received had any sort of insertable child, and so on and so forth until the entire object graph is covered.