Stop using Entity Framework as a DTO provider!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hi everybody uh welcome to another jet brains live stream uh this is a spicy one today uh you can see our guest here uh right now uh but before I introduce him uh let me a little bit of housekeeping uh I know the chat is really Lively right now people have questions uh some people have opinions uh so please put those in the chat uh I'll be gathering some of the best questions for guest today uh and uh maybe sprinkling them out throughout the live stream or maybe just holding them till the end uh so yeah thank you for joining us um the big question that a lot of people always ask on these live streams I think I saw somebody already ask it is this session live stream being recorded uh yeah yeah it is uh it's going to be on jet Marin TV uh if you haven't liked or subscribe to Jet brain TV yet please do so now it helps us out uh it helps us figure out what's good content uh so we can bring it to you uh but on that note uh let's welcome today's guest uh I had a great time talking to Chris in the back room here but let me give you a little introduction uh Chris kug is a developer uh badass as a service I love that uh currently working for a Swedish company called active solution uh he has over 20 years of experience as a web developer and Technical trainer uh having worked on projects ranging from online sports betting and sale racing uh and he's lived all over the world New Zealand Wellington but now is back in Stockholm good old stockhome with his wife so uh Chris uh yeah thank you for coming uh this has been a very spicy title uh it like when I put the blog post out uh there was a lot of comments right off the bat so some people cheering you some people jering you so we'll see how today goes yeah I've heard that so thank you for having me and letting me talk about my musings abouty framework yeah yeah so uh the stage is yours I'm G to be watching the chat so again folks uh ask as many questions as you have uh ask why is the sky blue no ask questions about EF core and we'll get them to Chris so Chris uh the stage is yours I'm going to be quiet and I'm going to listen cool thank you uh yeah so the talk today is is a bit about Entity framework and and some opinions I I have about that um my name is is Chris clo uh I work as as K said at a company called active solution here in Stockholm um I've been doing web dev for 20 plus years and I've had the fortune of be Fortune of being being a Microsoft MVP for the last 13 years I think um and yeah so the talk today is stop using Entity framework as a dto provider however I have renamed the talk it is now called stop using Entity framework as just a dto provider because I've had some feedback from people in the community and uh it's actually quite interesting I've been doing public speaking for more than 15 years now uh and I have not had a single talk where I've got as much feedback as I've had for this and it's very sort of double swort edge so on one side I have people saying like this is sweet I really enjoy what you're doing and I have people going and telling me things like you're using Entity framework wrong and yes this is an actual comment uh that I got online I'm not going to tell you who it was however I do want to clarify a few things before I get started so mainly because of that comment that I got there I want to get everybody on the page that all code is written in in in a context right so reading the talk reading my title for my talk and assuming what I'm going to say and telling me that I am wrong it's just slightly ignorant in my opinion and this is not just about my talk this is in general it's like we look at other people's code and we have opinions of how they do stuff honestly all of it is written in context uh and every single piece of code is designed with tradeoffs right and other people choose different trade-offs than you that's fine but can we just accept that different people people have different opinions and write code in different ways I just think that makes sense and my tradeoffs for this talk is I like like objectoriented programming and I I'm I'm probably a bit influenced by domain driven design so I like to have code that is objectoriented for real and slightly influenced by domain driven design as well and the code that I going to show is very opinionated the architecture I'm using for this talk it's not a lot of architecture but the the way that I'm writing everything is very opinionated in my way to write code however a lot of the EF parts that I'm showing off the way that you can use EF outside of what people normally do in my opinion is useful in any other scenario as well so just if you don't like my architecture that's fine if you don't like it the way that I use Entity framework that's fine as well but at least let's let people share what they think is useful and maybe you can pick up a few pointers here and there that you like uh so basically the way it hits you but listen to others and see if there are better ways to do it than you do it so anyway coming back to my stop using Entity framework as just a dto provider I guess we need to have a little chat about what do I mean by dto provider so if you take dto and you run off to Wikipedia and you look at data transfer object or dto it says in the field of programming a data transfer object is an object that carries data between processes dtos are simple objects that should not contain any business logic but may contain serialization or de serialization mechanisms for transferring data over the wire okay and then there's this this pattern is often incorrectly used outside of remote interfaces this has triggered a response from its author where he it reiterates that the whole purpose of dto is to shift data in expensive remote calls so that is the definition of a data transfer object and if we then look at one in in code it looks something like this right this is a dto it's a it's a dumb plain old CP object it has no logic it has public get sets for everything it has no encapsulation it has no functionality as such so we just get this no no functionality get sets all over the place stupid object that is a dto it's used for transferring things between processes so imagine that you have Entity framework in this case so we've got our web server and our web app and inside our web app is our code and we use Entity Framework and framework talks to SQL server on the DB server in the SQL Server process and inside the SQL Server there is process there is black magic and there might be a dto there should be kind of a dto between the SQL Server process and my process probably not because it's going to be a different format in a dto as such but that might make sense however between EF core and my app code I I don't think we need dets I think we can do it differently uh and that's kind of where I'm coming from um and I got get lots of people asking us what's wrong with that I've been using simple objects like that to access a database for years and so yeah sure we can do it like that and can start out with what's wrong with that uh and then I've been using objects like this for so the reason that you might have used Entity framework to pull up simple objects like that might be because if you go to the Entity framework core getting started page on on M on Microsoft learn you get information about hey you need to install the net cor SDK and then you scroll down you create a new project you install Entity framework core and then you you create the model and then you map your objects and there it is data transfer objects stupid objects just there to read data from the database to the mo to the to your application and it's fine because it's a sample it is basically a sample of how do you get data out of database and I I have no problem that people use Simple examples in their their demos the problem is that when you take this and turn this into your entire datab base access or your entire data access it becomes problematic which then pulls me into what's wrong with that once again according to me well where's the business logic like where do you put the business logic uh in inside of your for that data well obviously this answer answer for that is I use services or commands for that um and that's fine that's that's one way of doing it um in my opinion it basically means that you spread your business logic across a bunch of services all over your application which means that if you ever need to find what business rules are enforced on a specific object or a specific entity you have to go around all of your services and basically collect those little bits and pieces from all over the place I I dislike that but if that's the way that you want to build it I'm okay with that the other one is where is the data validation so how do you validate the data in your objects if you just have public get sets and you basically allow anybody to put anything into any property at all times how do you validate that and and not just from a how do you make sure that reference referential Integrity is not being compromised but actually how do you just do things like making sure the values are not null or they have a minimum length and all of that it's like well I put that in my services or commands Okay and once again you mean you're spreading it out across bu your classes because now all of a sudden all of your validation is in a bunch of different services so when I ask you what the validation principles are for a name for example you have to go and find either if you're lucky one specific service that updates the name and then find out the rules from in there or if you're unlucky you have to go to several different classes so to a figure out what the rules are and B make sure that they're actually the same and the validation is the same in all places now that is fixed by the classical comment of I put that in a validator class that my services commands uses okay problem with that is that you're still forcing the services and commands to remember to call that validation class to make sure that the validation is done correctly and if you forget to do that then all of a sudden you can have invalid data again so that's why we have set right so using set is is quite awesome um it does have some problems though um it's not really problems it's just that if validation is invalid or the data that you put into a set is invalid how do you handle that well the only way to handle it is to throw an exception and I guess the downside here if you aren't used to it is that a lot of people don't add TR catch around a Setter they will add TR catch around when you call methods but Setters well people just expect them to work because well validation is generally not done there apparently so I created a little example here and I want to keep in mind that my examples are always crap they they are it's really hard to write example code that is small enough for me to show within like a few minutes but complex enough to include the things that I want to show a solution to so my examples are contrived and probably very stupid and I agree with that and you can have opinions yada y but here it is so here's my S sample domain that I want to use it is U basically the DMV I it manages vehicles and their owners and it's uh the addresses for the owners very very simple and there's a many to many relationship between vehicle and owners and there's a one to many between owner and person and or owner slers and address and an address can be both a delivery address and an invoice address that's about it and database for this I think most of us would come up with something that looked like this we have a vehicle table weic owners table where we it's not just a connection table uh it's actually contains to and from as well for the owner so we know when they became the owners and when they got rid of the car uh we got a People table and we have a bunch of addresses with a type and is current so the type defines what type of address it is and is current whether or not it's the current address of that type for that person so using dto and services the stuff that I said that I'm not a big fan of it would look something like this so I have a bit of code here and I have a dto version here and I have two different versions uh the first one here is dto Rule so this is just pure dto like we would normally write them so the data stuff is up here we have some models we have an address in here and you can see it even has all of these nice database attributes or data attributes in here to our annotations to make sure that everything is set up properly uh they're very St simple they're all public get sets for everything like I see everyone else defining their objects when it comes to entty framework and once we start using that in my uh in my raw example here so I have two Services I have a person service and a vehicle service uh and we look into the person service so split into two that's the only reason uh first of all people tend to map these things yes they can be hidden behind um repository pattern or something like that that's fine um doesn't make a difference the the thing that causes problems in here is actually not getting things getting things is fine in this way because you just need to get data from the database and in that case a dto is fine but when you start going into set address for example then all of a sudden there's a bunch of validation logic in here to verify that the the address line and the postal code and the city and the country is not another white space and then uh there is another thing here where it basically says is there an existing address well in that case it needs to be set is current to false then we create a new address with is currently true we add that but there's also a business rule in here that says that we're only allowed to save or we should only save three addresses so if there are more than three addresses for this person then there's some business logic in here that removes any other address that happens to be in there and then we save the chains so we've got validation stuff in here up here we've got business logic coming out in here with address counts and things like that and the is current thing and if we go to the vehicle service it's not much better in here once again there are quite a few like gets but if we look at Set current owner for example then in here it pulls out the owner based on the first or default where two equals null and then if there isn't one then throw an exception uh new owner find the owner based on the ID then oh yeah the current owner if there is one then we need to set the two to date time today that's a business rule in there as well and then we need to create this coupling table object and add that it just it it spreads out all of these things into these Services which honestly it can be fine if that's if it's a simple crud application it is not a problem and if you're not service person uh you don't application Services you might do commands and queries instead and then you would put this into your commands but my problem with this is that this is not the way that I was learned to code I was learned that object-oriented programming actually connected uh functionality and data in one place and used encapsulation and all of that stuff and the things that DDD is talking a lot about making your code readable and understandable and things like that so that's what happens when you use dtto and services you end up with these stupid objects and a lot of code gets spread out across the application with validation and business rules and all of that the question then obviously becomes could we make that code a bit more more OB object oriented and and yes we can and the first version of doing that is one that I've done myself um don't blame me for that uh is we could wrap our Entity framework objects in more I don't I don't think opy is a is a real word but you more objectoriented kind of object as such so I guess the question is what does that mean and what would it look like well imagine that you have a vehicle dto like the one that I just used that had public G sets for everything but we take that vehicle and we wrap that vehicle dto in a vehicle class and then we put functions or methods on that vehicle class uh which basically has all the business logic and we can have all the validation logic on this thing as well so we don't put we don't need to put the validation logic and the business rules into the dto that Entity framework gives us but this allows us to put the business logic and the validation into a class where we can find it and as you can see here for Vin for example it goes vehicle.vin because it has that internal dto and for the current owner it goes for vehicle. owners. first of default blah blah blah so this is kind of like a pass through wrapper object which which isn't bad and if if we want to look at the way that that works I have like a wrapper version in here so in this case I have what I call entities so a person in here for example it takes in a person dto or a person model which is that dumb object that I'm talking about but then it adds all of these nicer things on top of it so basically get all addresses set delivery address set invoice address so we know how to set that instead of having to use like a an enumeration in set address um we can have private things in here so private things with business logic and validation so we now got the validation and and business rules around addresses inside of my person object instead where it's where it kind of should be in my opinion uh and name for example when you when you get that it's uh yes so I want to use a value object as well so I have this record called name uh which makes it a value object in the DDD sense uh then to get one of those actually have to create one of those every time or when you ask for it the first time because the dto just has simple first name last name instead of a name value object um the cool thing about this if if we want to be as such is that when we start using it so if you go to the person service for example these are exactly the same so the services are identical between both raw and and rapper now in here set person's address looks exactly the same but the code to actually use that object use that person object means hey get the person with ID and I now have a an extension method on the DB context that that returns person so this extension method allows me to put my queries into an extension method once again if you want to use um repositories which is a really good idea that's fine I just wanted something simple to show you that I need to get hold of a person but now once I have the person I can then go in and say hey I want to set the deliver address I want to set the invoice address and I want to save the changes or if you want to go to the vehicle thing with uh changing owner then hey Set current owner well all we have to do is we get the VIN or vehicle by the VIN that we pass in we get the person the new owner and then we call vehicle set owner and the set owner is responsible for making sure that all of that business logic and validation goes into that object so to me I just like the fact that this code here whenever I interact with my domain or whatever you want to call it becomes easy to read if you take a developer that goes in here and looks at this code it's going to be quite obvious I'm getting a vehicle by the VIN and if it's null then I return an error I get the new owner if there isn't one with that ID then hey return an error and then I call set owner and I'm done and then all of that logic is in there compared to the other one where there was validation logic and business rules everything spread out across the service so that that that works but then um I come along and I go but why why would you do that since Entity framework is an OM so it's funny because a lot of people don't seem to know be able and this is not a complaint to such but I've asked a few people and they couldn't actually say what stands for uh it stands for object relational mapper so I went online to this thing here I don't even know what Prisma IO is to be perfectly honest I just Google what is an omm to get like a good explanation I ended up on this web page and it says an omm or object relational mapper is a piece of software that designed to translate between the data representations used by a data by databases and those used in objectoriented programming now this part here designed to translate between we're not using it like that when we're just using dto objects once again for reading stuff and returning it to the client using dto is fine because we we just want to have what in the database basically sent to the client a dto is fine but if you want to manipulate and play around with it we are not actually translating the data representation in the database to our objectoriented programming we're taking the data representation that we have in database and we replicate it into our C code in our so-called objectoriented programming and then we start manipulating the data with service all around it so we can map it to the objects we want directly yes of course we can we can map it to whatever objects that's kind of what the OM is there for you design the objects that you want thinking that hey persistence is a technical or an implementation detail and then you make make the OM do what you needed to do to preserve your objects in the database now that's not completely possible at all times but that's what I think we should aim for so if we look at this this thing here we're back to my my stupid domain again very simple domain now I have a little problem here as a DDD person um and that's the fact that we call this thing owner slers in the middle and to me that kind of indicates that it's the same table in the database that's that's true but it's probably utilized from two different areas or two different subdomains or whatever you want to call it um because with a vehicle you have an owner but for a person has an address so just because of that I decided to split my project into two like I've done with the services but I'm going to split it a bit further so I'm actually going to create two different so-called bounded context or sorry subdomains one with Vehicle Management where you would manage all of the vehicles and owners and all of that stuff and then a people management where you would manage people's addresses and and things like that now that is interesting now the problem here is how do we how do we do this how do we get owner and person to go to the same database table with Entity framework and well you can do that there's something called table splitting or you can use multiple DB contexts so the cool thing about using multiple DB contexts in your pro project is that H DB context becomes a much smaller Le less complex thing so there's only configuration in one of DB contexts for that part of the domain that you're working on uh which can be really nice if you have a complex domain but you can't use migrations properly or autogenerated Migra migrations with those DB contexts because you can't generate migrations from multiple DB contexts and if you do generate migrations for just one of them it's going to cause problems with other ones and so on so there are there are pros and cons to that table splitting is another way of doing it that means that you have One DB context but it allows you to split your tables and use the same table for different types of entities which is a really nice way because it it means that you can not only map in my case person and owner to the same table it actually allows you to map your dto to to one table and pull up a bunch of things and map your entities or the things you want to manipulate to the same table and maybe the thing that you're manipulating maybe my owner doesn't actually need to have all of the information that's available on a person and a person doesn't need all of the information available on an owner so basically it allows us to map multiple things and to the same table which is really nice but each to his own I'm going to use table splitting um because it just it looks cool and I want to show it because it's it has some weird quirkiness to it when you start configuring it and an added bonus to this is that you might actually not need lazy loading so ENT framework core didn't even have Lacy loading initially and there are massive downsides to using Lacy loading uh but there's also problems with not using it because how much data should you read up uh initially and so on but if you start doing mapping towards like entities and aggregate Roots like you would do in in domain driven design you're probably going to cut off your aggregate route to not be huge which means that you might be able to load all data at once because you need a lot of that to make sure that your your entity is actually valid so it might remove laser loading which is quite neat in my opinion so this is when we go into a massive demo of how to map a domain more like OPI or however we want to call it so because of that I have this domain folder up here I have my tests in here and yeah so there are tests for both my uh raw and wrapper and all of this code is available to download from my GitHub if you want to but basically I'm going to recreate what I had before but I'm going to do it in a more object oriented way so in my domain project I have my uh Vehicle Management stuff I have my people management stuff I'm going to go into those in a second I have a little infrastructure it's just a service result so I dislike throwing exceptions uh that aren't actually exceptional so instead my services generally return a service result of te or something like that to Bas so I can return an error without throwing because throwing exceptions is a it might not be an exceptional case and B they actually have a performance implication when you do it so service results are nice uh as such so I'm using that in the data folder I have a a DB context as you can see it's fairly empty right now it's it's just inherits from DB context that's that's about it um I left a little comment in here um this thing here being able to log to the debug debug right line is actually quite ni when you're running your code locally so you can look into the debug to see what queries are actually being used at the moment so if you want to optimize your queries a bit that's nice and if you if you have a more complex domain than the one that I'm showing you and you end up querying and joining a lot of things you can split your queries in Entity framework so that instead of doing one giant question with a cran products with lots of data in it you can ask SQL Server to actually do multiple questions instead so there are going to be more question but less data which can can be useful if you're doing a lot of joints so I just left that in there if you want to have a look at it uh but that's it that's all I have and if we go to the Vehicle Management stuff uh which is where I'm going to start there's not a whole lot I have a couple of exceptions that's that are going to be thrown I have some dto that will be returned from my service once I've done what what's needs to be done so there vehicle dto owner dto I still use dto it's just not what I pull out a database in most cases and I have my my service the thing that I'm going to implement and it's currently throw not implemented exception for each one of them so that's what I'm going to be getting getting up and running so the first thing I need is I need a class so I'm going to create a vehicle class in here like that I'm going to replace that with a bit of code that code there so I have a public class vehicle and once again I start out by coding my projects like this this is not just a demo this is literally how I work on a daily basis I start out writing what I want so I want to have a vehicle it's have a list of owners that's going to be private um I'm making all of my Constructors private that's just me I used to use I like using Factory functions instead or factory methods because it allows me some flexibility if I ever need to change and add some inheritance in there it has a VIN so a vehicle identification number and as you can see I've actually defined that as a VIN which is a object a value object um in this case implemented as a record which encapsulate everything that has to do with a Vim so I'll get back to that and finally I have current owner which is basically you go through all of the owners you find the first one where two is is null and the previous owners are all the owners where two has has been set so we know that they they don't own the car anymore Vin is that value object I talked about so it basically takes a value it's a string but when you create one or try to create one it runs through some validation so it validates whether or not the past in value is a valid Vin based on this regular question because a VIN is 17 characters based on that format out there don't ask me why I know that it's not because I work with vehicles it's because I Google it um you can read more out of the VIN but it depends on where in the world you are and they're different I couldn't actually do more cool stuff with it um so Vin is nice I actually like value objects a lot because it allows you to en encapsulate um like little logic parts around a value so a VIN is just a value but it also has rules and logic built into it so that's kind of cool I'm going to move that to a different file and then I have an an owner so an owner has an ID which is actually the ID of the the person owning the car it has a name once again name is based on a a value object for first name and last name and it has a date time to and from it's all I need so those are my entities that I'm going to be using for this so I'm going to move these out into their own class or own file because I can of like that I don't like having multiple things in one place so there it is so youve seen the entities now they're really basic I know but once we have the entities we need somewhere to store the data and yes you can map everything with Entity framework and have Entity framework generate migrations for you I'm personally not a huge fan of that for a few different reasons it doesn't quite work in with the workflow that I end up doing with a lot of my clients so instead I tend to add my own migrations and so I'm just going to do a a couple of quick migration or a quick migration here so I'm going to do migrations and also it's interesting how many people have said that they didn't know that you can very easily uh create your own migration so you just create a class I have a little helper method for it here you just create one like that you give it a name it's like initial migration demo context there is and we import the things that we need now this is my migration and now I can start writing writing my own stuff it doesn't need to be autogenerated it doesn't have to have a snapshot C file and all of that fluffu that you get from generating results you just go in here and then you get well then I need to know how the database works and what well the thing is if you're going to design a database you probably need to know what the databas what a database is and how it works and otherwise ask someone else to do it that knows databases because databases are complex you don't need to know a lot though honestly to do my migrations here I'm going to add a a table here so I'm going to say migration Builder create table I'm going to create one table called Vehicles it's going to have two columns it's going to be a SQL Server identity column of type int called ID and there's going to be a VIN column which is a string with 17 characters and I'm going to put a primary key constraint on it this is not very complicated to write in my opinion uh if we go and we add a people table to store my my people my person objects person entities once again has an ID first name last name a primary key that's it if we add this is a bit more complicated so this this is the coupling table between the vehicles and the people so it's called vehicle owners it has a vehicle ID a person ID a from and a two and then besides the primary key it also has some foreign Keys down here it basically says Hey I want to map from the vehicle owners to the people full tables ID column and I want to have a Cascade in here and I want to map from vehicle owners to vehicles and vehicle ID based on the vehicle table and ID and once again Cascade so if this if stuff gets removed it gets removed um so that's it uh I also oh yes I need one more thing in here I keep forgetting this every single time I do this talk which isn't very often to be forget honest I keep missing this we need some indexes so I'm just going to query based on the VIN in in a lot of cases and it's not the primary key so it won't get an index by default so I'm adding an index for the VIN column and I'm adding an index for the person ID in the vehicle owner table because I will be querying that a lot as well honestly I will not be querying that a lot it's a demo but you get the general gist so if we take the down this is so if you roll back your migration and honestly please don't roll back migrations if you did an incorrect migration create a new migration and roll up to that because being able to run roll back migrations in your pipelines when you automate your your U um deployments is actually a bit complicated it's much easier to just add another migration that reverts the thing that you did wrong before instead of um doing it down but I'll add a down in here as well so if you revert this migration it will remove these tables in the correct order that will give me a database now there is a little problem with my code and that is the fact that my owner class here is actually a combination of the people table and the vehicle owners table which causes some problems and it it might be possible to map that uh really complicated um over the two tables but I've chosen to actually Bend to the will of Entity framework and make a little change in here I'm actually going to add a an entity called person and now somebody's going to go and say well Chris you didn't want to have stupid objects now I don't and honestly this not a stupid object it has a private set it has a read only name because I'm not going to be modifying this thing and nobody's ever going to see this this is a this is only for my mapping stuff so once I have that class in place I'm going to update my owner a little bit and replace this so my owner object is going to be mapping a person that is private so it's all kept inside and I'm wrapping that in my owner and then when you get the ID I go person. ID and when you get the name I get person. name but the date time the two and from here they come out of the same table so basically I'm merging two tables into one object by hiding the second table as a private field instead that makes it fairly easy yes it causes a little bit of ugliness in the owner class but anybody using the owner class will not see that because it's all Tada encapsulated which is one of the things we do with objectoriented programming um okay so once we have the database we have our entities we need to do some mapping and now here is where a lot of people go Chris you're doing it wrong well actually yes you might be thinking that and I might be doing it wrong but mapping things in Entity framework with only data annotations won't allow you to do all the mappings that Entity framework can do for you and I've yet to have a project where I don't have to do at least one mapping manually because the the annotations aren't enough and I'd rather have all of my an all of my mapping in one place and having a bit of it as annotations and a bit of it as manual configuration which is why I do all of my Entity framework as manual configuration because I actually enjoy doing that um and also I don't need to put data annotations on my beautiful clean domain objects that don't have to do with persistence so they shouldn't have um dat annotations on it my opinion fully aware of that so in here in on model creating is where we map our entities so in here I'm going to map my first entity I'm going to map just going to include this so what you do is you just say model builder hey I want to map an entity called vehicle I want it to be mapped to the vehicle's table in this case I probably wouldn't even need to do two table because the convention would put it in vehicles if I'm not wrong but I do like having That explicit because anybody coming in here reading don't need to know about the conventions because if you've worked with Entity framework you know the conventions that's fine but when the new developer comes on the team or if you get a junior developer on the team they won't know all the conventions going in here and looking at two table even a chicken would be able to figure out that that is mapped to the table Vehicles right so I like that next one I map this property here this is actually a shadow property and what that means is that if I go to the vehicle class there is no ID and the reason I didn't put an ID on here is because well Vin is the natural identifier of a vehicle the ID the integer ID is just there for the database to be able to do mappings uh or joints so by doing it like this and using this property of T and passing in a string if it doesn't find a property or private field called ID it will actually just generate a magical unicorn property that Entity framework manages for you it doesn't need to be in your class sweet I can ignore that it's a pure implementation detail then I'm at my VIN I will get back to that in a second because Entity framework has no idea what a VIN is so you need to manage that then I map the owners and once again I use this has many of T and passing in a string now in this case the vehicle actually has a private field called owners keep in mind this is case sensitive so it has to be called owners with a lowercase o because it finds a private field with that name it will map to that private field making sure that I got like an encapsulated value that I can use and I want to make sure to Auto include it so I don't have to go do include do include do include when I do my queries to Entity framework this will always include it for me because I always want to have all of my owners with me now keep in mind if you're doing something like this and you have an unbounded list that might grow to be huge do not UT include it it's a really poor way of doing it because it means that hey I just want to get the the VIN for this car or verify that it that it exists and then all of a sudden you've read up like thousands of rows because of that don't do that but for me there's not going to be thousands of owners of this car I hope um and in my demo there's definitely not going to be so that's fine then I tell entty framework to ignore these two properties the reason that I ignore them is because they are calculated properties so they cannot be handled by Entity Framework thus they should be ignored and finally I tell it that it has a key and it is the ID and because the ID is a shadow property I need to Define it as a string I can't go in here and do like a Lambda going x equals greater than x do ID so that's kind of nice so the only thing that's problematic in here is the VIN so Vin is a VIN which is a value object and Entity framework doesn't know how to handle a VIN because it's never seen one before now it has this cool thing called has conversion and it basically says hey if you get a VIN and you need to put it into the database then go ahead and pull out the value property of that VIN to get the string that goes into the database and if I get a string from the database go ahead and call uh Vin do that wasn't all I want vin. create to go ahead and create a new vin for for you so being adding that has conversion thing allows us to query based on a VIN retrieve a VIN and manipulate a VIN and Entity framework knows then how to do stuff with a VIN which is kind of nice uh okay so that was the vehicle and then uh the next thing to to map is uh the owner so we'll go ahead and add an owner mapping once again I want to map The Entity owner it maps to that col table there it has an a shadow property called vehicle ID because that doesn't exist on the the object it has one person which is a private field called person and I want to Auto include the person so it's always there because if that's null then half of my object is broken and then ignore these two properties because they're calculated and finally this has a composite casy so actually the the primary key is made up of both the vehicle ID and the person ID and what else have we got well we got the person right so we need to map the person as well because the person is being used here so I'm mapping that as well it to the P table now here is a a funky thing when you're mapping um a a value object that is not just a simple string you can't actually use um has conversion because has conversion only gives you access to one column at the time so instead you can use this thing called has complex property and then you tell it this is the complex property the name because the name has first name and last name and there are two columns in the database called first name and not last name I want you to take those two columns generate a new object called a value object called name and use that as the property instead and then Entity framework knows how to use value objects which is really cool and finally I set the key for for the person it's kind of all I need so with this mapping and my migrations I can start implementing my service so let's go to the vehicle service here it's as you can see it's not implemented and I thought think we'll we'll start with the get vehicle by Vim so implementation for that uh so first of all it starts out it takes a string so my service my application service that gets requests from maybe the API or MVC controller or whatever other thing the other adapter or Port I'm using will pass in a string and then this I will go and check hey Vin can you try create a VIN from that string and if that works if that doesn't work then return an exception now the next step here is I need to get hold of my vehicle from the database and this is a source of a lot of conversation and a lot of yelling and a lot of telling people that they're dumb um and also a lot of really cool mansplaining about what the repository is so I am not going to use a repository because I don't want to get into discussing what is or is not a repository and so on and also my demo needs to be kind of short so I've actually decided to simplify this a little bit repos are to be used I completely agree but for this case I'm actually doing I'm injecting my DB Contex straight into this class but Chris you shouldn't no I probably shouldn't but I don't care for demo it works fine and honestly if you're building a small system and you don't intend to be testing it heavily and it it's just doing Simple Things I Don't Mind If you inject your context that's fine however what I dislike is I don't like people adding queries inside of your services going context set. blah blah blah so instead what I'm going to do is I'm going to go in here and I'm going to add a directory called data and then inside the data directory I'm going to CL add a class called demo context extensions and inside here I'm going to add a class an extension stass public study class with an extension method called vehicle within the vehicle with win is an extension method on the on demo context it takes a VIN and it allows me to set as no tracking as well so for any reads I do I don't want Entity framework to be tracking them for performance reasons so I pass that in then inside it I just take the context I get a set of vehicles I cast that into an i queriable of vehicle if I passed in asno tracking I call asno tracking on it and then I do a query down here and as you can see there's no problem querying using a my VIN value object because Entity framework knows how to handle that so with that in place I can basically just go await context. vehicle with vin passing in the VIN which is unfortunately nullable so I need to add an exclamation mark and I don't want it to be tracking so as not tracking by the way I I looked at this while I coded now after I coded it it should probably do with tracking equals false it's just negative negative it's just makes weird but yeah I do that I get my vehicle and the last part is once again if you're doing query only I urge you to probably use dtos and and read straight to dcos and I will show you a little bit about that later on actually I want I will show you part of it but for this very simple thing I'm just mapping one vehicle and I want to turn it into a dto and now somebody's going to say hey automapper can do that for you yes it can but if you're like me and you don't need to add a bunch of extra stuff for simple things you can go Ahad head and just go dto extensions like that add a class that looks like this so I create this simple little class called dto extensions it adds extension methods called two model to vehicle and owner and all it really does it it takes the vehicle and returns a new vehicle dto it takes an owner returns a new owner and once I have that in place I can go in and say vehicle. two model that didn't come out right to model like that and that now means that I get an entity of type vehicle which I can work with but then I return a vehicle dto from the service so that my MVC controller or my API or whatever can just call this service get stuff done and then return the model straight away without having to do any interpretation in in there end so that's vehicle by VIN the next one I have is vehicle by ID and the reason that I have this one as well is that I want to show it I told you that I don't like having the ID there assume that you have a legacy system that requires you to fetch it by ID and I didn't want to have the ID in my vehicle that is still actually quite manageable so the code would look something like this so I'm going to need a vehicle with ID on my context so I go in here and I add another extension method uh it's going to be this thing we vehicle with ID extends demo context now the question is here it's very similar to vehicle with vin the problem is that x. ID doesn't actually exist there is no ID on vehicle there's nothing in here that says ID there's no private field no nothing it's a shadow property but because it's a shadow property doesn't mean that we can't use Entity framework to query for it so EF has this really cool static class called EF which has a U property method that says Hey I want to query a property of type int it's going to be available on this object I have here my vehicle and the property is called ID now EF property of in returns in so I can then go and say like that so even though I don't have the property ID on my my actual entity I can still query for it even if it's just a uh Shadow property so that gives me this nice just get the vehicle with ID if everything is fine return a model otherwise return an error we have get owner with vin uh so get owner with vin is a bit interesting because if we look at that it does pretty much the same thing tries to create the VIN gets the vehicle by VIN looks if there is a current owner if there is not returns not found or otherwise it returns to owner. current model or to model now here is where somebody is going to tell me that that is very inefficient Chris and I actually kind of agree because right now I'm reading up the vehicle which is going to include every single vehic owner uh that whole list of owners and the vehicle and luckily it's a simple object but if it would have been a more complex entity I might have read out a lot of stuff from the database but we can make that a little bit better we can actually we can remove that and try and do this instead so yes now I I told you I didn't like have queries in here I just have the query in here because it was easier to show you I would probably hide this behind my extension method as well but what I can do in here is I I can pull up my set I can query for the vehicle that has that VIN and then I can choose to only select parts of that object so in this case I'm looking at the owner property which is a is a private field so I need to use the EF property thing and then I only want to pull out the first owner where the Y do2 so the owner's two is null so this allows me to add actually write a query to the database that will only pull up that specific owner without pulling up the whole object and then I can just say if there is no owner then return an error Now problem with this code is that this will actually return null both if the VIN is incorrect and if the VIN doesn't have an owner so if you want to be able to say hey I couldn't find the car and not just hey I couldn't find the owner then this code is no good but EF can handle that as well so if we do this version once again I do my vehicle set I select my vehicle but then I do a projection so I basically say hey EF can you go and select a new object and can you SE select the the VIN of the vehicle in the VIN property and the current owner into the owner property and then my first or default a sync now returns a VIN owner ER and then in my projection I can see if there is no projection that means that the VIN didn't exist because my wear Clause failed but if there is a a um projection and there's no owner then it means that there is a car but it doesn't have an owner and I'm allowed to send these two different errors depending on what the situation is so projections is really powerful way of actually taking a complex large object and query for just a specific thing that you need which is quite nice um okay so that was uh get vehic with owner oh sorry get current owner um let's go with ADD vehicle as my next one so ef9 once again try get the VIN get the vehicle now get the owner now to be able to get the owner I actually need to go and get a person so to be able to get a person I need another extension method so once again it just pulls out a set of persons or people and then return the first default with that ID so I get my owner I create a a vehicle I don't have a vehicle create method so we have to create a vehicle method like that the create vehicle basically takes a VIN and a person it news up the vehicle and sets the the current owner based on the person that I passed in and then I just add that to my context and I save my changes which is quite nice and all of the logic IS F fairly easy to read in here as well now the last one I've got that I haven't implemented is Set current owner and it's not because it's very complicated uh but if we do once again try create the VIN get the vehicle get the new owner and then call set owner on the vehicle once again set owner is missing so we need to put that in there so oops let's impude that so now we put our business logic around owners in here so if there is a current owner and I'm trying to set the new owner to be the same who already owns it then yeah that's an exception you can't do that you might be able to just do a return here and you'll be fine with it and it would be more item potent and then if there is a current owner then it needs to end its ownership so I don't want my vehicle to know that to end an ownership I need to set the two fi instead I want to add um a method like that so going to go to the current owner oh sorry I'm going to go here and I'll add a method down here all that does it sets the two date but that that's the business rules like end ownership could mean something else but now my vehicle doesn't need to know that you just say hey you don't own this thing anymore and then I create a new owner added to the owner's collection and return the owner that was just created and out here I just say changes when I'm done with it nice and clean and simple in my opinion I like it it for me it's easy to read now that's actually all you need need to do I need to do in Vehicle Management now people management is obviously very much the same thing so I'm not going to go through and do all of it it has the only thing that's really interesting in here is like we have a person the person has a bunch of addresses uh it has a name it's the same value object but in this case it's actually so that you can change it which is why there's validation in here uh the address is the only thing that's really interesting it's an abstract base class uh and then it's inherited into delivery address and invoice address so in this case delivery address and invoice address has exactly the same field as address the only reason that I want to have this is because I want Entity framework to map it to those types so I can go and say if address is delivery address in C and it basically looks at the type for me but edti framework also allows me to map other things so if you haveck hierarchies of objects you can actually say that hey this is the base class and then for this type I want you to map these columns and for this class I want you to map these columns and so on so you can actually have a whole h key of objects being mapped to the same type of table which is quite nice um and yeah that's about it the only other thing is like in the person object there is a set delivery address and a set invoice address which now means I don't have to pass in an an an what type of address it is actually tell it what type it is in the method call and they just piggy back on set address which then creates either a uh delivery address or a invoice address and I have the logic around the number of addresses to save is in here as well so I don't have to put that into my service those are the only things that are interesting the person service is already implemented there's not a whole lot to look at in there to be perfectly honest the thing I've got left is the data stuff The Entity framework stuff so first of all I'm missing a table to be able to do this I need an address table so I'm going to do an addresses migration it's going to be an EF migration going to be sequence two uh addresses migration I don't know if that's spelled right probably somewhere in the right neighborhood the demo context uh include all of these things there's probably a shortcut for that like that and I just need one migration in here all I need is this simple migration here it's it doesn't look simple because it's long but it's just it's it's one table just add an addresses table these are the columns that you need the only thing that's interesting here is the type which is a string and and is current and the person ID and then add a foreign key between person ID and the people table create an index on personal ID because that's going to be used a lot and in the down let's do drop that table that's my migration for adding addresses to the thing should be fairly okay now I could go into my demo context and add more stuff into my on model trading but you can sort of realize that this is quickly going to get out out of hand right I've got the world's smallest domain with like seven objects or something and I it's already uh like 40 lines of of mapping code so better nicer version to do with that is actually I'm going to go into my my uh data folder here my people management and I'm going to add a new class in here and I'm going to call it person type configuration like that going to replace it because I'm lazy so the person type configuration is going to implement I entity configuration of person and then I can put all my mapping Logic for the person stuff for the Migra stuff configuration in here and then I can have one class for each thing that I want to map with Entity framework which makes it nicer so mapping that is fairly simple it's map to table people this is not a shadow property by the way it's a it's a private field so person does have an ID here for different reasons it has some addresses it auto includes them it has a complex property called name we should ignore these two because they're calculated properties so inside person to get a uh delivery addresses or the current delivery address I look at the addresses of type delivery address where is current equals true and for invoice I do the same thing so I can actually use of type here because I got Entity framework to map it instead of having like a type property that I need to check so that's the mapping for that and then I also need to map one more thing so I need to map um I need to map my uh my address as well so I'm going to move that into separate file so mapping the address is not very complicated it doesn't actually include the mapping for the properties at all because convention says that if the property is named the same thing is the column then it will be at automap so all I need to do is tell it what table to use I'm adding a ID Shadow property again I'm adding a type Shadow property so this is going to be this that string in the database that is the type invoice address or delivery address and then I map it using what's called a discriminator saying that hey the type property on this thing which is this Shadow property here if the value of that is delivery address then hey map it to a delivery address if it's invoice address map it to an invoice address and this then allows us to have like chains of of um inheritance that allows us to have as I said other properties and things like that but in this case it's just very simple just two different types with the same properties on it now once I have my two I entity type configuration of T I can go to my DB context and we can go in here and we can say model builder. apply configurations from assembly we get the current type do assembly and that means that it will actually automatically look for any I entity type configuration in this assembly and apply it one thing to keep in mind they are not applied in any specific order and in some cases the order of your mappings do actually make it different for different reasons so some cases this won't work for you and you would have to do it but you can actually go and apply at least use the I entity configuration one at a time and say this is one and this is one and you can get them in the right order and not just do them in different orders but at least you don't have to map everything inside your demo context or your DB context like this so that that's kind of it let's see if this actually works so I have some tests down here in my test folder let's go and comment those in so these are going to test my code to see if it actually Maps as it should because I'm pretty sure that if I didn't show you that it works somebody would say that I was cheating and the code that I wrote would never work I'm going to build that see that it builds to begin with okay so I'm I'm terrified here right now it did build that's good we go to the unit tests we have our domain test here let's go and run our tests um okay that failed um Okay so first of all I just want to mention so what I'm doing in my test is I have a little test helper that actually spins up migrates the database for me creates a transaction around every test ABS data verifies it and checks it and all of that but it basically it runs the migrations uh as part of a nunit um xunit frame sorry xunit framework thingy here so it migrates database for me based on my migrations now I did get some exceptions in here uh which was um to be perfectly honest expected because I I get this weird exception that says no suitable Constructor was found for entity type person name hasht name the following cannot B first name last name blah blah blah so this this exception is actually crap the reason that this exception happens is because of conventions is Entity framework and this doesn't tell you what is wrong so the thing that is wrong if we go into let's see I'm just going to make sure that I do this in the U the right place so I'm going to have to go into the demo context so because I'm mapping two people uh two people and owner to that same people's table it actually has a convention that says that it's going to add the the type under UND type name underscore and then the property name so it expects the the name to column to be called person underscore name person or first name and person unor last name that is kind of annoying and it has to do with uh with the that is in is in where did I go am I in the right place I should be in the right place here it is uh it has to do with that one so that one is going to be incorrect unfortunately so I'm going to do like this so because the convention is wrong I actually have to go and say Hey I want you to map a name but the first name should map to a column called first name and the last name should be mapped to a column called last name so it doesn't use that Convention of concatenating type and name and I need to do the same thing inside of my uh person type configuration in here so just mapping it specifically to the column because yeah conventions are conventions and they don't always work that would be one part let's run the the tests again okay so I get another exception luckily um I did know that this was coming um it says cannot use table people for entity type persons since it already being used for entity type person okay that that's weird so it's it's because it's already used for person and potentially other entity types but there's no linking relationship so this is yeah table splitting is funky uh so it's not saying that I'm mapping two things to the same table but they don't have a relationship and honestly they shouldn't have a relationship but you need to tell Entity framework that they do and how do you do that you go in here and you add this really funky line that says the Vehicle Management person the person in the other subdomain has one nothing with one nothing and has a foreign key in this this person that is called ID now ask me to explain that and how that works and why it's done in a name that nobody understands and I can't ask the EF team they can explain it to you probably and I'm not sure that even they can but that is the way you have to do do table splitting it is documented so that's fine so now if we run the tests again they come back green all except for one so one here is failing it says expected one it came back minus one and the the test that I'm running is this thing here and it says returns person dto if ID exists and the check is doing is that the ID of the result being returned is is one and it came comes back at minus one and that is obviously by Design because I want to show you something if you go in here to not that one but that one in my two model for person in the people management it says minus one hardcoded here what it should be is the ID of the person now the problem is that person doesn't have an it has a private ID field because I don't want to have the ID exposed it's only there for legacy purposes so it needs to be there but I don't want to expose it so whenever you use a person you get like an ID property because you shouldn't use it now I could go ahead and expose that and make it public which means that anywhere in my code I had a personal object and thought when person dot it would say ID I just like that a nicer more objectoriented way of doing that would be adding an interface that like this I have ID of T we move that we tell person that it implements I have ID of T and the ID is an INT and then I can ask it to implement that and it gets whoops that wasn't what I wanted I want Implement missing members but I don't want to implement like this because that wouldn't help me at all now it's once again just a public property so if I did this it would be a public property and and I wouldn't have gained anything but I can say I have ID of t. id id of int and that means that it can't be public anymore now that means that I can still access the ID but it's not publicly available so basically if you go in here and you say person Dot it won't have an ID field but being me I know that it implements I have ID of int so I can then go and cast it to that and ask for the ID like that which means that it's hidden from the rest of the code but it's available for me when I actually need it and finally the last part here is that I run my tests and if I have sacrificed enough chickens to the demo Gods it goes green and it does so all of my mappings are working so basically con like the end result of this and I want to mention is basically try to go ahead and map your objects like you want them to look so write your your entities with the functionality with the encapsulation that you need that you want and then use entity Frameworks omm capabilities to map private fields and internal things so you get encapsulation and get real objects I just prefer that now I am talking about editing things I'm not talking about returning and gets not queries but for commands if if you want to just do queries then mapping to simple objects is fine I'm I don't mind that uh if you use Aggregates and go DDD way it means that you can use Auto include instead so you can can don't have to do do include everywhere which is quite nice if you do go all the way down with aggates and agate Roots use specific queries if you if you want to for read performance so if read performance is a problem then do um projections to get only the thing that you need uh and honestly if you want to go really really specific on your queries Entity framework as of version eight or something like that actually supports kind of the same thing you do with for example Dapper you can write your own SQL Creer and have it mapped to a non-mapped entity in C which means that you can write your own very very performant queries straight through Entity framework as well when you need that um yeah I mentioned the table splitting or query splitting feature you can turn on query splitting per query or for the whole context and then opt out of it if you want to so table query splitting allows you to minimize the amount of data that you get without getting so you don't have to get cartisan products coming back I would also recommend not doing bidirectional navigation because B directional navigations don't actually show an intent in in where you should go and also bir directional D navigation tends to allow you to go from one thing to another thing back to another thing to another thing to another thing back and forth and all of a sudden you've managed to read up your entire database so in my case for example you could get get a person sorry you get a vehicle and then you get the owner and then from the owner you could get all the owner's vehicles and then you could get all from one of those Vehicles get all those owners and I promise you if you keep traversing that the entire database would have been read into memory which is bad um I dislike Microsoft idea of mapping both IDs and entities so if you're relationships they tend to map like the the blog post ID and the blog post the good thing about that is that if you set the blog post ID and then call save changes a sync all of a sudden your blog post is populated uh so but that's also the weird one it's like okay so that if I set the ID and I call a save then all of a sudden a completely different thing is now populated for me so I don't know if that other thing is populated for me by default or not and blah blah blah I dislike it I prefer using uh The Entity if I need that or just the ID if I don't need actual entity as such and my final thing I want to mention is please do not migrate your data as part of your application setup so in your program. CES do not migrate your application there or your database sorry and the reason for that is that that looks really good on your local machine and on your local machine I am well aware that that is a good idea to do and I don't mind it there but put it behind if environment is local or debug or whatever the reason is that if you then take your code and deploy it in a load balance environment I'm not going to say Asher or AWS specifically any form of load balance envir environment and you spin up four of these things at the same time they all try to to migrate your database three of them are going to fail and those three are actually going to fail their startup and their application is going to be dead so your four replicas are now down to one replica because that was the only one that succeeded and you have to reboot other ones so how do we migrate our database in that case well Entity framework actually makes that fairly easy you go to the terminal you go to your source code which is for me in here and then you say netf and then I have some codeing here I have that one you say netf migrations script D- item potent don't forget that if you don't do that you're going to get a SQL script that can only run once which is not good in a deployment pipeline this will make it I important output migration SQL you run that and when you run that it's going to generate some SQL for you but it won't because it's not saying that hey I couldn't find a DB context of type blah blah blah you can configure it in configuring or use add DB context if you use addb context you have to have an application I don't have an application on configuring yes you can put things that has to do with this in configuring it tell it to use SQL Server because it's I need to get SQL scripts but instead of going into my demo context and adding more things to my on configuring there is actually a little helper thingy that is looks like this it's called an I design time context Factor which is basically used to create a context for design time which is basically your EF tools uh you put this in here you implement the create DB context you say that hey I want to create a DB context options builder for my demo context I want it to use SQL Server I don't give it a connection string because it doesn't need one I only need the actual DB context and then I return a new DB context based on that just because that is in my project if I run this now again it will actually look through my project it will find that I design time DB context Factory and it will go generate my SQL scripts and if we look at the SQL it's in here so here are my SQL things which is nice now I dislike that idea because I work a lot with deployment pipelines and if you do that you know that it's a pain in the butt to try and run SQL scripts in the deployment pipeline it means Powershell uh Powershell modules or whatever bash thing you're using and you need to connect to the database and run the script and everything the EF guys have actually about this uh so they have this thing here which is it's not new but it's fairly new so you're going to say EF migrations bundle instead and you do output to an exe you run that you now get an x file instead or exe file or on Linux you get an executable which is in this case called migration XE if I now run back migration. XE and I give it dash dash connction actually I think I have this I thought I had this I did not Das Das connection and I need a connection string I'm going to show you my connection string and everybody's going to go no Chris don't it's a local database and I promise you I would never use the password my very secret password in production so I take that I paste that in I run that the migration. XI will actually have everything needed from net to do a connection to the debate database run the migrations for me I don't need to use Powershell anything I get a pre-made little migration tool for which is nice so run that as part of your pipelight instead of the SQL stuff and please do not migrate it as part of your application that was it so I want to thank you all for listening uh I hope you got something out of it uh the code that I've been working with is available at that address however there might be a tiny little bug in this code I do believe that it has to be lowercase all of it the font I'm using is uppercase only so you need to do bitly slf core ef-- dto in lower case for it to work or use the little QR code that's it it worked woo that was really cool Chris uh but now I have to change my password so I don't know very secret password ask your password you yeah it's it's fine it's uh I'll I'll figure out I'm seeing 176 questions and I'm terrified of switching over to that time because no no there's no no no this is uh there's a lot of good conversation happening some of them uh first of all I think your presentation style is uh amazing it's really funny engaging so I enjoyed it uh one of our guests uh watching also enjoyed it uh it was nice to see the anger and impatience of someone who has been developing software for a long time so I agree with that uh people are questioning your ethics uh are they saying so are we just going to lie to Entity framework uh when you're doing the mapping and yeah sure the Entity framework I I see Entity framework as a tool um and and tools are to be used and that includes sorry I shouldn't say that I shouldn't say that tools as in people should be use but Entity framework is a tool it's there to do our bidding to be perfectly honest which is why I I get a little bit annoyed by everyone purely using it to do dto that is that is Entity framework telling you how to do it turn it around tell framework how to do it and yes lie to Entity framework as much as you can yeah is thate in general if you if you can light and get your code to do anything then lying is fine you hear you heard it here first people lying is fine in code to get okay uh sorry I didn't mean to take you out of context uh no there this is a really good question from Serge here um you know you ended up writing a lot of your migrations uh Entity framework famously has autogenerating migrations uh what are the advantages of using that c API to write those migration versus just like executing SQL scripts uh so executing SQL scripts don't have a so so there I think there are three parts there there's there's one part you can do your migrations using the EF tools to autogenerate migrations for me that that causes some problems especially since I'm doing table splitting uh table splitting and it I think it works pretty well but I've also work in a lot of projects where we use duplicate uh DB contexts for different reasons and then that doesn't work so that's why I started doing migrations migrations versus SQL scripts SQL scripts do not have the ability to roll back in any way shape or form uh which is like once in a while that is actually a good idea uh also it I find them easier to read uh the migrations in C sharp to me they they are easy to read but sequel scripts as a as a SC script as such is is complet fine as well I have no problem with that whatsoever I'm if you if you feel comfortable writing tsql better more than you are comfortable read right in C then go ahead the only thing to remember is that that bundle exe file that I used which I really love for deployment purposes that is not going to be there for your SQL stuff so if you want to do it with SQL then you have to build your own little net tool that basically does the SQL stuff for you with your files yeah or I guess you could use embedded resources and and kind of like shoehorn it in uh so that's an option I would also add to that though like if you are on a mixed skill team and you have dbas and stuff uh maybe it's their responsibility to help you design and write those queries so maybe in that instance squl makes a lot of sense uh I like this comment uh from one two uh they said I'm feeling I'm feeling this approach so uh you have I'm very happy to hear that because I like I heard I've heard both sides of it like I've got I've got that as well it's like there there are some good good takeaways for a lot of people but I've also heard that I'm doing it completely wrong so I assume that somewhere in this uh there there's going to be you're completely wrong as well yeah uh one interesting question from Colin is if business logic is in the entity uh how do you handle di for things such as like logging uh do you have those kind of um so Plumbing things there are a couple of ways to do that one way would be to say that your logging should actually be in your application service and not inside your entity because if your entity is supposed to reflect the real world a vehicle doesn't have logging right but the the thing using the vehicle could do the logging for you that's that's one way to think about it and that I use that a lot so I but if you want to put logging in there or any other form of di I know that the DDD world is kind of torn when it comes to di for your entities entities framework has something called interceptors uh and there is one Interceptor type called IM materialization Interceptor that allows you to plug into Entity framework and say whenever you go and new up one of these things go and add um this thing to it so you can go and do your own thing so you won't be able to do Constructor injection but you can do property injection uh so if you want to get a logger in there declare a a logger field and then use an IM materialization Interceptor to say that Hey whenever you create one of these types go and set the loger properly using and that the actual Interceptor has di I'm pretty sure I I used that I'm actually on the way to write a blog post about similar things so hopefully there will be one on my blog in the near future yeah blog posts are always good if people if you're doing something interesting write a blog post uh definitely it's good for the community um it's good for you maybe sometimes you forget oh what was I doing back then oh yeah I remember the number of times I've Googled things and found my own blog is ridiculous but it's there's two parts of it with blogging it's like part is uh yes it helps everyone else and yourself when you go back to it but it also for me it just enforces my learning I remember things that I've blogged about a lot more than I I remember things I haven't blogged about just a comment in the in the chat here I saw that the the jet brains your your link was to bitly EF core dto in all uppercase it needs to be all lowercase oh okay uh I'll fix that I'll fix that in the description once we re-upload the video um there's kind of a Common Thread uh going through uh when you were doing like wrapper objects uh one of them uh Dane here says pain lives in rapper objects performance terrible when doing sets of data um so it was about like reading data um let me get the other one up there as well uh the problem with the wrapper object is you might have multiple kinds of vehicle dto for different purposes so I think both these individuals are talking really about the query part of building an application uh what are your thoughts there so for querying um I wouldn't use wrapper objects at all in that case I will actually map either map my other dto objects straight to database to make really simple queries just public get sets and dto uh or I will use the the mapping that I have and then use projections to project it into a dto instead uh wrapper objects in general that I showed here was more of a cautionary tale because yes there is that pain of when you get a lot of them you have to iterate through what you get from the database and then inject them into the new thing so you get a double set of entities that needs to be projected up and all of that stuff and I've had some people say that oh no no you do the dto from the database uh which they don't call a dto they call a database model and then you use automapper to map that into your entity uh and then you work with your entity but that that's even worse in my opinion because that means that that Entity framework can't actually track your entity which means or the the the object which means that when you do a save you actually need to pull it up from the database and then do an automat recall from your entity back into the dto and then save that again so you kind of lose that that change tracking from Entity framework so wrapper objects is a to me it's a last sort of way to do it if I don't have any other way to do it yeah you won't believe me but no one in chat mentioned automapper it's kind of wild I don't know what happened there I think that's that's good maybe people aren't using it as much I'm not saying that aut m is bad in any way I'm just saying that it it seems like it's been overused in a few places uh yeah no comment I'm not gonna say I'm not gonna I'm not gonna walk into that one uh uh yeah and you know what let's end on a positive uh people loved oie so uh anytime you can use the phrase oopie go ahead uh I think people love that uh so go for that uh but let's see if there's any other last comments um no I guess that's it uh let's wind down Chris uh this has been an awesome talk uh you're welcome to come back anytime uh you know I love I love these hot takes spicy opinion talks uh it's always fun to just hear people's thoughts their experiences and stuff like that uh so yeah that was awesome uh if folks want to know more about jein rder and what we do with jet brains uh you can head on over to uh let me hide this current comment first uh you can head on over to Jet brains.com riter uh also check out our blog uh me and my developer Advocate colleagues are always writing about net there so you can kind of check out what we're doing at jet brains or maybe just technical topics uh yeah follow us on social media and uh again uh we have a YouTube channel you're watching us now so I think you know about it but but if you don't know about it tell someone who doesn't know about it I think it's aren't you supposed to go say click the follow link below or something like that well well wait wait up Chris I'm gonna give you the honors but if you want to see some of uh Chris's blog post uh follow him on his blog at fearof oblivion. uh you can also follow him on social media at zeroc call is that how you say that zero call yes okay you kind of know what it means but if you're not then it's weird so Chris okay I'm gonna give you the honors because I always do this at the end of live streams but go ahead you can you can do the YouTube thing go ahead do it Oh you mean the if you like this Channel please click the follow link below dude you're professional this is amazing this is awesome yes like And subscribe hit that notification Bell uh share it with your friends and colleagues uh and yeah let us know in the comments if you like this live stream uh if you want to see Chris again again uh give him give him some props this is awesome so on that note Chris everybody thanks for joining us uh we'll see you at the next live stream thank you for having me [Music] bye
Info
Channel: JetBrains
Views: 25,738
Rating: undefined out of 5
Keywords: webinar, rider, resharper, entity framework, dto, dto provider
Id: N_eLotlcjXo
Channel Id: undefined
Length: 87min 19sec (5239 seconds)
Published: Thu Mar 21 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.