Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@florianfanderl66742 жыл бұрын
We do the exact same. Works flawless. I'm pretty sure you did the other stuff right in your codebase, but for other users: if you just have getter and setters, it's probably not a domain model. Your domain model should have behavior (aka functions). If they don't live there, you just built another (crappy) ORM.
@MilanJovanovicTech2 жыл бұрын
"Another crappy ORM" 😂
@Numinalis Жыл бұрын
This is the pattern I use because I use Dapper. Except, instead of placing these memento methods inside of your domain entity, you can do even better. Have a private class inside of your repository that extends the domain entity with these methods. Also make the memento class a private class inside of the repository. Now, this logic is fully owned by the persistence layer. For a long time, I used to struggle with domain models leaking details that were necessary for infrastructure, and it really bothered me that I was forced to either do that or use a specific ORM. I finally feel satisfied with the above approach.
@MilanJovanovicTech Жыл бұрын
Why not just extension methods in the Infra layer? Maintaining private classes is a bit tedious (although I completely understand the idea)
@Numinalis Жыл бұрын
@MilanJovanovicTech That's a great point. You certainly could do this. I will give it a try! I appreciate all of your videos and explanations, Milan. Thank you so much for making these concepts more widely known.
@steve-wright-uk2 жыл бұрын
We use this pattern with Entity Framework. The only difference in our implementation is that the To/From methods live within the Snapshot class, not the Domain model class.
@MilanJovanovicTech2 жыл бұрын
So your EF entities are flat, and you convert to/from rich domain models?
@steve-wright-uk2 жыл бұрын
@@MilanJovanovicTech Correct
@christianlavigne8742 жыл бұрын
I like this approach! This way the domain does not have to be aware of the snapshot and it can all be encapsulated in the persistence layer.
@slobodanmikaric2180 Жыл бұрын
I have a question, when should we dispatch Domain Events. Ideally we do it right after the save method and now I am wondering if they are left out?
@kostasgkoutis8534 Жыл бұрын
How do you access the getters/setters of the domain model then? Reflection magic or you bundle it all together?
@montanomariano2 жыл бұрын
I recently had to do something very similar and yes, it indeed becomes more tedious with large domain models!
@MilanJovanovicTech2 жыл бұрын
If it works, it works 🤷♂️
@zikkrype Жыл бұрын
I guess it’s time to create series of videos about event sourcing with projections and snapshot. That would be nice
@MilanJovanovicTech Жыл бұрын
I definitely want to tackle that!
@Vityhard2 жыл бұрын
As you told, it could become a very complex when you have an entities with a lot of relationships. In my project I’m using JSON columns from latest EF core 7.
@MilanJovanovicTech2 жыл бұрын
Nice option!
@geraaksenov4688 Жыл бұрын
The Member model doesn't have any relations, how do you cover these without ORM? As you pointed out, email, name and date are all DB-supported types. What if Member would have e. g. a list of Group as a property, and each Group has list of their Members?
@MilanJovanovicTech Жыл бұрын
You cover them manually, sadly...
@thomaswoods1365 Жыл бұрын
I'm finding the Id assignment in FromSnapshot is not working because of protection levels in the entity base classes. Do protection levels need to be softened to make this work?
@MilanJovanovicTech Жыл бұрын
Protected is fine
@thomaswoods1365 Жыл бұрын
@MilanJovanovicTech I changed from private to protected in the set accessor and that worked. Thanks for all this great content Milan!
@patrykklimas43982 жыл бұрын
We are using similar pattern but outside of domain - in the Infrastructure. Repository is creating Domain object based on it's constructor. Using your presentation (in the domain) you can create domain object without any validation and you are creatating classes which are not connected with domain (snapshots) in the domain. What do you think about it?
@MilanJovanovicTech2 жыл бұрын
It all revolves around the same idea 😁
@nebularazer2 жыл бұрын
Interesting pattern i already used without knowing the name. In my python project i separated my Domain Entities from my ORM Model by having To/From methods on the ORM Models. I would like to go with plain sql too, but i find it difficult to convert rows including joins (all members with all their addresses) back to some model i can represent as json in my api for example. Also change tracking is not a thing with this approach...if i only update the FirstName of a member in your example the database request will still set all 3 properties, right? I would like to see another video with a more complex Domain Entity / Aggregate Root.
@MilanJovanovicTech2 жыл бұрын
ChangeTracking is definitely not a thing without an ORM, or at least it's not easy to implement. For mapping complex types, Dapper solves it really well by allowing you to map the response into multiple types. I'll show an example of that, you gave me a good idea for a video.
@ramytawfik9168 Жыл бұрын
something i do not understand please milan Do you mean that we can use mapping library to handle the necessary conversions between our Rich Domain Model and Simple Dto and removing the snapshot pattern?
@MilanJovanovicTech Жыл бұрын
You could, yeah
@ramytawfik9168 Жыл бұрын
@@MilanJovanovicTech Thanks very much
@num1nex3372 жыл бұрын
When you inject IDbConnection into your repository, how do you handle disposing the dbconnection after the query is done ? Is it something that's handled behind the scenes ?
@MilanJovanovicTech2 жыл бұрын
Yes, the context is scoped to the request, so it will be disposed of after it completes
@iliyan-kulishev2 жыл бұрын
The best approach might be to have some kind of IDbConnectionFactory and in the the persisting/quering method create the IDbConnection and wrap the Dapper calls in a using statement.
@davittonoyan6537 Жыл бұрын
Don't you need to dispose the DbConnection or it is done by Dipendency injection?
@MilanJovanovicTech Жыл бұрын
Taken care of by DI
@DimonSmart Жыл бұрын
Thankyou Milan! You always make a great video! I'd love to know about more complex object with a collection of sub-objects inside. It looks like a problem to save such objects in efficient way. As far as I understand we have to manually implement kind of ORM change tracking. And it looks a bit complicated. Or we have to query whole domain object again and do some tricky manipulations to know if we have some parts inserted, updated or deleted. While googling this approach I found the idea to have a dictionary with DomainObject -> Snapshot (or ORM with change tracking object) object. Looks like this could help but I' not sure.
@MilanJovanovicTech Жыл бұрын
You'd pretty much be implementing an IdentityMap which is what EF's ChangeTracker does for you anyhow. I wouldn't bother with implementing that on my own, as there are too many edge cases.
@DimonSmart Жыл бұрын
As I understand the Snapshot Pattern could be used for domainmodel and datamodel separation only for simple one table cases?
@christianlavigne8742 жыл бұрын
How would you go about re-hydrating more complex domain object with children?
@MilanJovanovicTech2 жыл бұрын
Load them all using a JOIN in the database, or send multiple SQL queries, and then map that into a domain model. This would include multiple snapshot classes also, on for each domain object.
@antonmartyniuk Жыл бұрын
I like using this approach even when I have a EF Core. That way my DTOs are DDD entities and models being used in Repositories are simple and stupid Dbos. That way my mapping is simple and straightforward and I don't have any overhead of model transformations on the persistent layer. P.S.: DTO naming is relatively speaking, the models returned by WebApi is also stupid and mapped from DDD entities
@MilanJovanovicTech Жыл бұрын
What's the benefit with EF Core however?
@antonmartyniuk Жыл бұрын
@@MilanJovanovicTech that way DDD level is only on Service/CQRS level. And if you decide to use or not use DDD in the service that way you don't have to rewrite the whole application. Based on the complexity of the service layer you can build it the way you want and other layers might not know about DDD and don't have to know about it
@adisilagy2 жыл бұрын
Hi Millan, Two questions: 1. How would you deal with returning a List of members. 2. Would you recommend simply applying an SQL mapper to the value objects so then you want need snapshot entity
@MilanJovanovicTech2 жыл бұрын
1. Return a list of snapshots, and convert them 2. One option. But it's the same. You just moved the mapping somewhere else.
@jacobjacob80622 жыл бұрын
Where do I find your repository Gatherly?
@MilanJovanovicTech2 жыл бұрын
I share it on my Patreon: www.patreon.com/milanjovanovic
@ezecel92 жыл бұрын
Hello, are you going to upload your recent conference about modular monoliths? Thanks!
@MilanJovanovicTech2 жыл бұрын
Yes, I'll post here when it's uploaded (on company's YT channel though)
@wboumans2 жыл бұрын
Can't you use EF Value Converters?
@MilanJovanovicTech2 жыл бұрын
The point is not using an ORM
@steve-wright-uk Жыл бұрын
Via the domain model constructor
@MilanJovanovicTech Жыл бұрын
✅
@KangasniemiJerri2 ай бұрын
"without an ORM" - I mean... Dapper is an ORM?
@MilanJovanovicTech2 ай бұрын
Object mapper... Where you do all the work. Not a fully-fledged ORM