Get the source code for this video for FREE → the-dotnet-weekly.ck.page/multiple-dbcontexts Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
I would like to see a deep dive into migrations. Specially changes to a production database and how that would work with changes to the schema of a database. Thanks for all the Awesome videos!
My team uses two database contexts. One of the connection strings is configured with the ApplicationIntent=ReadOnly flag. Above these contexts, we have a context manager and it decides which context is to be used depending on the purpose (writing/reading). Both contexts addresses same listener, but connects to different servers: primary (write) and secondary (read).
how does the context manager knows that which db context to use ? do u pass something like a parameter in for every db context initialization mentioning whether its a read/write?
I have another use-case - create multiple instances of same DbContext (that use different connection strings) to query different shards of your data (meaning each shard is a separate database) in parallel
Greate video! I am junior software dev and this question came to my mind few weeks ago. Cool explenation and clarify example. Just in time to get rid of my concerns :) Thx
When using multiple db contexts I recommend using external tools for database migrations like FluentMigrator or DbUp. It's really easy to get lost in EF migrations. Before you notice you spend most of your time fighting with your models to generate the right migration's code. Also it's troublesome to migrate all the db contexts before deploying applications in your release pipeline.
🎉 Excellent, I'd like If you can give It a little zoom in on those tiny letters that are hard to read from our side, maybe increasing the environment font size
I have two contexts in the same assembly, and I also have separate Fluent API configurations in different folders. In the OnModelCreating method, I have to manually ignore the entities from the other context. How can I specify configurations based on the folder path and not the assembly? How should this be handled? Thank you!
Hello, I have 2 contexts and both have memory tables, one is the archive db. I need to retrieve records from the archive db for queries exceeding 3 months, and since there is pagination, I need an IQueryable query. Do you have any suggestions?
I'm trying to build a clean architecture for all of my projects in one solution and since the databases already has data so I'm trying to scaffold the databases first and i have multiple db context because of that still i can't make it to a full working project wish you make a video on scaffolding, multiple schemas, database first, clean architecture
Hi Milan, what are your thoughts on common entities between db contexts, specifically when you have a complete DDD structured app using the repository pattern and IUnitOfWork? I am wanting to create a database per application type in my solution and then have a set of common tables that are always present in all application databases e.g. tblOutboxMessages, tblEmailHistory etc.
What if I want to use Separate Db per request. Like getting TenantID from Header with each HTTP Request to generate Connection String and then DbContext ?
Hello Milan, once again, thank you for the rich content you present on your channel. Could you discuss in a video, what would be the most elegant strategy so that I can create a replica in a NoSql database (MongoDb for example) to serve as a read-only database? I know I could use EF Interceptors, however, it would be interesting to have a generic form without having to specify the model as in the example shown in the Outbox Pattern video.
@@MilanJovanovicTech It could be asynchronously too, but I believe that doing it synchronously right after the commit in the recording database would help a lot, even though we know that this could impact the system's performance, the problem with doing it asynchronously I believe is that would be the guarantee that the data was written to the read database.
Useful content. I nice stuff at the end about drawnbacks and how to use transaction but also you didn't mention that you can use connection from one DbContext in transaction or you can control connection to explicitly through some connection factory.
@@MilanJovanovicTech thank you for video, can we please have extra video on how to correctly make transactions. As already mentioned there's tech possibility to use common connection but how to configure scopes properly, how to inject connections, how to manage services etc. Thank you
11 месяцев назад+1
Hi Milan. Great videos as always! Thanks for your hardwork and high quality videos. Wondering if you can create a video showing your recommendation to avoid downtimes (or minimize it) when deploying changes in the DB schema with Entity Framework. Thanks in advance.
Why not just initially place contexts in different assemblies? Each of them will have own default migrations folder and no -DbContext argument will be required - it will be detected by chosen assembly.
I think this example was helpful in terms of understanding the limitation and the CLI. But yeah, in most cases they would live in different assemblies.
@@MilanJovanovicTech Personally, I do not appreciate partial examples, especially those that contain practices that are considered bad. Placing contexts into separate assemblies is not a big deal and it also gives an opportunity to show how to manage such contexts using visual studio and to make a comparison between approaches in one video.
Hi Milan, Great Video. I have a question. you did not establish navigation prosperity within LineItems and Product Entities. So how to get Order details with the name of the Product in that order?
If using DbContext without DI can you do new DbContext() on top of controller and use it in Actions or do you need to do using(var db= new DbContext) to handle Disposing each time ?
Nice explanation, thanks. I have it set up very similar. Is there any particular way of joining data from two datacontexts (e.g. showing product names in the order)?
Excellent content! One question that remained and I couldn't find anything specific on the internet, making it necessary to relate tables with different contexts, what would it look like? For example: I created a context to deal with all tables related to user inputs and a context to deal with all system calculation tables, but a relationship is made within the DbContext (in the scenario of a single DbContext) to say that input table A is a foreign key in calculation table B. What would it look like in the case of two DbContext?
I don't think it's doable, and I'm certain it's not suggested to do it that way. You can probably create the FK references at the database level. In general, it's not recommended to mix these DbContexts at runtime
Great tutorial Milan, I love following your videos. I'm curious, in the case of a modular monolith, the creation of an order would occur in the Orders module which would not have access to the ProductsDbContext. In that instance, how would you access the products needed to create an order? Would the Order module query the Products module using a service abstracted using an interface?
In case of a Modular monolith, you would only care about a Product ID from the Order module (plus some pricing info probably). In that case, you will grab the data at runtime using the public API of the products module - as you suggested. Another solution is to store a local copy of the data, but then you need to maintain that...
Would that be ok to use multiple dbcontext in a single application just to separate small semantic part of the database. For example: all that is related to users is in one dbcontext, everything related to products/orders/etc. In another one used and this kind of goes for all "main features". I guess this goes into the Modular Monolith? Asking because we have a database over 200-300 tables and it sounds a bit overwhelming to have one dbcontext for everything.. What do you think? My only concern is about performance of having to write multiple queries for features that covers multiple semantic contexts (i.e. multiple db contexts)... Not sure if that's clear enough... ? Any way, thanks for your very helpful videos and for being awesome 😎
@@MilanJovanovicTech okey, so how to handle this use case if we need to communication in this case ? In my case I have two contexts, one for identity (not aggregate root) and one with only aggregate roots ?
Long story short, if the contexts target the same DB instance, make sure they use different DB schema names or the migration histories table will get messed up. Got it.
@@Hallo503 It depends on your goal. If your application is multi-threaded and it needs to work with DB from different threads simultaneously, then yes - in each such thread you need to create its own separate DbContext. In other words you cannot share DbContexts between threads. This is due to DbContext is not thread-safe. But if your application is single-threaded, then you can create and use multiple contexts in it, just in one thread. This is what Milan showed in his video. Notice, that in such case there will be no "concurrently reading the database" via several contexts. This will be sequential access through one, then through another context.
You need to specify how it will be converted to and from a primitive value in the database using the HasConversion method on the property in OnModelCreating.
Hi, great video and good explanation 😊 a pleasure to follow and easy to understand, thanks for sharing I actually have a question, what if you have a table that is shared across both dbContexts? Both are pointing to the same physical database, how to divide migrations in that case? My assumption is that all the migrations will be only under one dbContext, even if the table is shared across both. Thanks in advance )
Cool video! 🔥 Could you please tell me how to create several identical DbContexts, but for different databases. Probably an array of DbContext 🙄 The database structure is completely the same, just different SQL servers. (No migration needed) I'd like to have a connection to all databases and get data from some base depending on post parameters
@@MilanJovanovicTech I need to load data from all databases. I use services.AddDbContext to add one connection. But now I need to do it multiple times, using different connection strings. I could create a new instance DataBaseContext each time, but I don't think that's the good idea?
Thanks for covering the scenario where the entities in each context are completely different and they have no overlaps or joins between them. However in real-world circumstances this seldom is the chance, and you have different sub-domains that need to share the same logical entities (ie: tables and IDs), and I’d love to know how this would be dealt with via multiple contexts. For example in your example orders need to reference products, so even if you have two different “catalogue” and “orders” domains, these should NOT reference different tables with a separate schema, as this duplicates information, creates multiple versions of the truth, and overall throws out the entire “relational” benefits of a database out the window. Same thing happens with any data that is linked to a user. Sub-systems in domains are generally hierarchical in nature, so Users/Accounts might be managed by one system/module, but multiple other sub-systems/modules need to refer their entities to these user tables. Would love it if you could dive into these “overlapping entities” scenario - perhaps in another video - as basically any system I’ve built ever always had this notion of sub-domains needing to link/refer to domain agregate root entities within another, even when you are disciplined and split out the dependencies so there are no cycles (ie: hierarchical sub-domains) and keep strict access to sub-entities through aggregate roots.
That's a great suggestion, and will certainly require a more in-depth video to answer!
11 месяцев назад+1
@mbradea visualize a microservice architecture. To avoid creating dependencies between them and making synchronous calls, the owner of the data should push the information to the consumer. The consumer then saves a copy of the data, and uses that. So yes, ideally they should be different tables. The source of truth is always the owner of the data, and the consumer has a copy with eventual consistency. It doesn't need to be an exact copy, the consumer can manipulate / transform / aggregate the data to better suit it's need, but they will always be a copy and never a source of truth. In a modular monolith you should follow the same pattern. However, a trick I use often to simulate a copy of this data without spending the time to create this information pushing between boundaries is to create a view that access the required information and map it to a query type in the db context. Being a query type I know my consumer will never change the information, and being a view I can create the necessary transformations to return the data as I want instead of creating a dependency on the original.
@@MilanJovanovicTech no big deal, I think it was sort of unavoidable to repeat the word "database" many times in the video 😁 And words tend to lose their meaning when someone says them in rapid succession, right?
Get the source code for this video for FREE → the-dotnet-weekly.ck.page/multiple-dbcontexts
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
Can I ask for a discount on ur course I’m divorced and don’t have to much on spending account please help
I have already used multiple Ef cores, but your lecture is beneficial for me to watch again.
Awesome, glad it was helpful :)
I was coding the base for a modular monolith project, and I saw the notification. Just happiness.
Sweet 😁
I would like to see a deep dive into migrations. Specially changes to a production database and how that would work with changes to the schema of a database.
Thanks for all the Awesome videos!
Great suggestion!
Really good one, thanks a lot :) these tips will definitely safe many devs from figuring things out the hard way
Hope so!
My team uses two database contexts. One of the connection strings is configured with the ApplicationIntent=ReadOnly flag. Above these contexts, we have a context manager and it decides which context is to be used depending on the purpose (writing/reading). Both contexts addresses same listener, but connects to different servers: primary (write) and secondary (read).
So you're actually using the context manager, and it know which DbContext to use?
@@MilanJovanovicTech yes. That was a goal of this approach
how does the context manager knows that which db context to use ? do u pass something like a parameter in for every db context initialization mentioning whether its a read/write?
I have another use-case - create multiple instances of same DbContext (that use different connection strings) to query different shards of your data (meaning each shard is a separate database) in parallel
Something similar to DB per tenant
Oh man, excellent! thanks a lot. 🙏🏾
Can't wait for you to do a video on multitenancy.
Coming soon!
@@MilanJovanovicTech
Greate video! I am junior software dev and this question came to my mind few weeks ago. Cool explenation and clarify example. Just in time to get rid of my concerns :) Thx
Glad it was helpful!
When using multiple db contexts I recommend using external tools for database migrations like FluentMigrator or DbUp.
It's really easy to get lost in EF migrations. Before you notice you spend most of your time fighting with your models to generate the right migration's code.
Also it's troublesome to migrate all the db contexts before deploying applications in your release pipeline.
Why not combine EF to create scripts with DbUp to execute them?
🎉 Excellent, I'd like If you can give It a little zoom in on those tiny letters that are hard to read from our side, maybe increasing the environment font size
Which letters specifically?
Awesome content! Thanks Milan
Sure thing! I'm planning a V2 of this video with Hangfire
Awesome, as always!
Thank you! Cheers!
I have two contexts in the same assembly, and I also have separate Fluent API configurations in different folders. In the OnModelCreating method, I have to manually ignore the entities from the other context. How can I specify configurations based on the folder path and not the assembly? How should this be handled? Thank you!
The second argument of that method is a Func which you can use to filter the types :)
Hello, I have 2 contexts and both have memory tables, one is the archive db. I need to retrieve records from the archive db for queries exceeding 3 months, and since there is pagination, I need an IQueryable query. Do you have any suggestions?
Not really
Thank you milan. Very nice.
Thank you too!
I'm trying to build a clean architecture for all of my projects in one solution and since the databases already has data so I'm trying to scaffold the databases first and i have multiple db context because of that still i can't make it to a full working project wish you make a video on scaffolding, multiple schemas, database first, clean architecture
That could be a good idea
very helpful
Glad you think so!
Hi Milan, what are your thoughts on common entities between db contexts, specifically when you have a complete DDD structured app using the repository pattern and IUnitOfWork? I am wanting to create a database per application type in my solution and then have a set of common tables that are always present in all application databases e.g. tblOutboxMessages, tblEmailHistory etc.
Yeah, I reuse that across contexts
What if I want to use Separate Db per request. Like getting TenantID from Header with each HTTP Request to generate Connection String and then DbContext ?
Then just manually create the context or use a factory
Hello Milan, once again, thank you for the rich content you present on your channel.
Could you discuss in a video, what would be the most elegant strategy so that I can create a replica in a NoSql database (MongoDb for example) to serve as a read-only database? I know I could use EF Interceptors, however, it would be interesting to have a generic form without having to specify the model as in the example shown in the Outbox Pattern video.
And we would asynchronously create this replica?
@@MilanJovanovicTech It could be asynchronously too, but I believe that doing it synchronously right after the commit in the recording database would help a lot, even though we know that this could impact the system's performance, the problem with doing it asynchronously I believe is that would be the guarantee that the data was written to the read database.
Useful content. I nice stuff at the end about drawnbacks and how to use transaction but also you didn't mention that you can use connection from one DbContext in transaction or you can control connection to explicitly through some connection factory.
I didn't want to make it too long, but great point!
@@MilanJovanovicTech thank you for video, can we please have extra video on how to correctly make transactions. As already mentioned there's tech possibility to use common connection but how to configure scopes properly, how to inject connections, how to manage services etc. Thank you
Hi Milan. Great videos as always! Thanks for your hardwork and high quality videos. Wondering if you can create a video showing your recommendation to avoid downtimes (or minimize it) when deploying changes in the DB schema with Entity Framework. Thanks in advance.
Ah, that's a tough one! I'll see how to make that into a video.
When I have more than one layer in the project
How do I perform the migration process?
The same? Just target the proper project
Do you have a video explaining this? @@MilanJovanovicTech
How to implement Uow pattern for this approach?
You don't - each context is a separate UoW
i got the dbcontext in different libraries. do i have to do the map in the api for all my queries?
Why can't you do it at a lower level?
I planning to use two dbContext in my winform app
one to deal with sql service and the other deal with local sqlite,
what do you think about that?
Smart idea
Why not just initially place contexts in different assemblies? Each of them will have own default migrations folder and no -DbContext argument will be required - it will be detected by chosen assembly.
I think this example was helpful in terms of understanding the limitation and the CLI. But yeah, in most cases they would live in different assemblies.
@@MilanJovanovicTech Personally, I do not appreciate partial examples, especially those that contain practices that are considered bad. Placing contexts into separate assemblies is not a big deal and it also gives an opportunity to show how to manage such contexts using visual studio and to make a comparison between approaches in one video.
I'm using one dbcontext and DB for parallel queries.
I have custom DbFactory to make sure every parallel query has its own DB Context instance.
Do you mind sharing code, will see if could use some idea
@@mediaatul not for sharing but for parallel SQL queries with EF core.
Interesting!
It doesn't make a lot of sense, I've had it
@@user-xm7sh3vw8o SQL parallel requests doesn't make sense?
What about micro services architecture when it’s required to use different db for each service?
Different DB - different DbContext. Should work like a charm.
can we use different database such as oracle and sql
It should be OK from what I saw. It's just that you should use oracle to ef lib, like in the beginning of video.
Absolutely. They are completely different connections, so they could be on different planets if you want!
Yeah, you definitely can. And this would be one of the reasons you'd want to do this in the first place.
Hi Milan, Great Video. I have a question. you did not establish navigation prosperity within LineItems and Product Entities. So how to get Order details with the name of the Product in that order?
Different DbContexts - can't do that.
How could you apply multiple DbCOntexts for a multi tenant application with per tenant database?
I need to do a multi-tenancy video ASAP
If using DbContext without DI can you do new DbContext() on top of controller and use it in Actions or do you need to do using(var db= new DbContext) to handle Disposing each time ?
You should definitely handle disposing each time
Isn't the dbContext automatically disposed when the request ends ?
What about using TransactionScope and enlist the single transactions from each DbContext?
No idea how that will behave when using different DBs 🤔
Nice explanation, thanks. I have it set up very similar. Is there any particular way of joining data from two datacontexts (e.g. showing product names in the order)?
Nope, you can't use joins between different DbContexts
You can first query the Products, and then store that info (duplicated) in the Order
Excellent content! One question that remained and I couldn't find anything specific on the internet, making it necessary to relate tables with different contexts, what would it look like? For example: I created a context to deal with all tables related to user inputs and a context to deal with all system calculation tables, but a relationship is made within the DbContext (in the scenario of a single DbContext) to say that input table A is a foreign key in calculation table B. What would it look like in the case of two DbContext?
I don't think it's doable, and I'm certain it's not suggested to do it that way. You can probably create the FK references at the database level.
In general, it's not recommended to mix these DbContexts at runtime
Great tutorial Milan, I love following your videos. I'm curious, in the case of a modular monolith, the creation of an order would occur in the Orders module which would not have access to the ProductsDbContext. In that instance, how would you access the products needed to create an order? Would the Order module query the Products module using a service abstracted using an interface?
In case of a Modular monolith, you would only care about a Product ID from the Order module (plus some pricing info probably). In that case, you will grab the data at runtime using the public API of the products module - as you suggested. Another solution is to store a local copy of the data, but then you need to maintain that...
Would that be ok to use multiple dbcontext in a single application just to separate small semantic part of the database. For example: all that is related to users is in one dbcontext, everything related to products/orders/etc. In another one used and this kind of goes for all "main features". I guess this goes into the Modular Monolith?
Asking because we have a database over 200-300 tables and it sounds a bit overwhelming to have one dbcontext for everything..
What do you think?
My only concern is about performance of having to write multiple queries for features that covers multiple semantic contexts (i.e. multiple db contexts)... Not sure if that's clear enough... ?
Any way, thanks for your very helpful videos and for being awesome 😎
Yes, logical separation in your code is good use case. But writing cross-context queries will be problematic for sure.
Great video
Glad you enjoyed it
Is it ok to separate domain dbcontext and identity dbcontext?
Yes
I really like the Visual Studio dark theme you are using. Would you share which one it is?
It's native dark theme + ReSharper syntax highlighting
Thank you@@MilanJovanovicTech
Hello, do you have any idea about how to manage domain events across those multiple contexts?
You don't, they're kept separate
@@MilanJovanovicTech okey, so how to handle this use case if we need to communication in this case ?
In my case I have two contexts, one for identity (not aggregate root) and one with only aggregate roots ?
I use 6 dbcontexts. 3 bounded contexts with one read and one write dbcontext each
That's a rich application :)
Long story short, if the contexts target the same DB instance, make sure they use different DB schema names or the migration histories table will get messed up. Got it.
✅
Hi Milan. can you cover in the futere video LoggerMessage pattern ?
Maybe, good suggestion
Does unit of work work on multiple dbcontext?
How would you implement it?
What's the use case of using multiple dbcontext instead of one?
Did you watch the video?
@@MilanJovanovicTechnice :D
Milan, how are you?
Are you using Git Copilot?
Doing great, and you? I'm not using Copilot
@@MilanJovanovicTech why when you typing the VS autocomplet the code?
@@FabioGalanteMans ReSharper
Thanks for sharing the information. One thing, what's your opinion on using DBUp vs EF Core Migration?
How about EF Core for generating migrations (SQL scripts) and DbUp for running them?
@@MilanJovanovicTech that would be interesting to see if you have anything ready around it.
is it possible to use multiple dbContext objects to concurrently read the database?
@@dmitrymezinov9238 so it is possible, but I have to explicitly create a new dbContext for every thread?.
@@Hallo503
It depends on your goal.
If your application is multi-threaded and it needs to work with DB from different threads simultaneously, then yes - in each such thread you need to create its own separate DbContext.
In other words you cannot share DbContexts between threads. This is due to DbContext is not thread-safe.
But if your application is single-threaded, then you can create and use multiple contexts in it, just in one thread. This is what Milan showed in his video.
Notice, that in such case there will be no "concurrently reading the database" via several contexts. This will be sequential access through one, then through another context.
As long as it's a different DbContext instance it should work
How can we set value object as ID in EF core?
You need to specify how it will be converted to and from a primitive value in the database using the HasConversion method on the property in OnModelCreating.
Define a value conversion, or check out Complex types in EF 8
Different databases, different contexts can be associated with queries?
What does that mean?
Hi, great video and good explanation 😊 a pleasure to follow and easy to understand, thanks for sharing
I actually have a question, what if you have a table that is shared across both dbContexts? Both are pointing to the same physical database, how to divide migrations in that case?
My assumption is that all the migrations will be only under one dbContext, even if the table is shared across both.
Thanks in advance )
Yes, you can exclude an entity from Migrations for a particular DbContext
Can different database instances and different contexts be associated with queries?
What does that mean?
@@MilanJovanovicTech Two different contexts, can you query jointly?
Cool video! 🔥
Could you please tell me how to create several identical DbContexts, but for different databases. Probably an array of DbContext 🙄
The database structure is completely the same, just different SQL servers. (No migration needed)
I'd like to have a connection to all databases and get data from some base depending on post parameters
Why not just switch the connection string?
@@MilanJovanovicTech I need to load data from all databases.
I use services.AddDbContext to add one connection. But now I need to do it multiple times, using different connection strings.
I could create a new instance DataBaseContext each time, but I don't think that's the good idea?
Can you do a video on IULD identifier and how you can use it with dot net 8
Been planning to for a while, but never got around to do it 😁
@@MilanJovanovicTech thank you Milan for all the hardwork you put in. Do you mind sharing some pointers on this topic.
👋👋👋👋
I did multiple dbcontext simply becasue I had to separate my identities and items(products and services) also a read-only context.
That's a common use case 👌
Thanks for covering the scenario where the entities in each context are completely different and they have no overlaps or joins between them.
However in real-world circumstances this seldom is the chance, and you have different sub-domains that need to share the same logical entities (ie: tables and IDs), and I’d love to know how this would be dealt with via multiple contexts.
For example in your example orders need to reference products, so even if you have two different “catalogue” and “orders” domains, these should NOT reference different tables with a separate schema, as this duplicates information, creates multiple versions of the truth, and overall throws out the entire “relational” benefits of a database out the window.
Same thing happens with any data that is linked to a user. Sub-systems in domains are generally hierarchical in nature, so Users/Accounts might be managed by one system/module, but multiple other sub-systems/modules need to refer their entities to these user tables.
Would love it if you could dive into these “overlapping entities” scenario - perhaps in another video - as basically any system I’ve built ever always had this notion of sub-domains needing to link/refer to domain agregate root entities within another, even when you are disciplined and split out the dependencies so there are no cycles (ie: hierarchical sub-domains) and keep strict access to sub-entities through aggregate roots.
That's a great suggestion, and will certainly require a more in-depth video to answer!
@mbradea visualize a microservice architecture. To avoid creating dependencies between them and making synchronous calls, the owner of the data should push the information to the consumer.
The consumer then saves a copy of the data, and uses that. So yes, ideally they should be different tables. The source of truth is always the owner of the data, and the consumer has a copy with eventual consistency. It doesn't need to be an exact copy, the consumer can manipulate / transform / aggregate the data to better suit it's need, but they will always be a copy and never a source of truth.
In a modular monolith you should follow the same pattern. However, a trick I use often to simulate a copy of this data without spending the time to create this information pushing between boundaries is to create a view that access the required information and map it to a query type in the db context.
Being a query type I know my consumer will never change the information, and being a view I can create the necessary transformations to return the data as I want instead of creating a dependency on the original.
The word "database" has lost all its meaning to me after this video lol
Database? Database
Why?
@@MilanJovanovicTech no big deal, I think it was sort of unavoidable to repeat the word "database" many times in the video 😁
And words tend to lose their meaning when someone says them in rapid succession, right?
@@MilanJovanovicTech btw, I'm new to the channel but you seem to produce high quality content Milan!
Keep up with the good work