Mapster, the best .NET mapper that you are (probably) not using

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nick and today i'm going to show you the best.net mapper that you are probably not using and that is mapster now before i dive into the code i want to preface this video by talking about how i feel about mapping because time and time again every time i do a mapping video people are commenting on whether you need or you don't need the mapper and i'm going to give you my take just so it's on record so there are two sides in the story and one side is saying that mapping should be handled manually meaning you should write the mapping method that maps from one object to the other and the other side is saying that mapping is a machine's job and it should be done dynamically i personally stand more on the second group but not always my personal take is that if you can be asked to do the mapping manually then use a mapper and that's fine but be very very careful with two important rules which by the way also apply to the manual mapping first always unit test your mappings including ensuring that your mapping is correctly configured and make deploying code impossible without those tests passing like bake it into your ci and the other one is do not mix any of your business logic in the mapper do not make any external calls do not try to be fancy and use any dependencies during the mapping process do not get any information for the object you are mapping into from a shade the internal source through the mapping process because this is abstracting information that should not be abstracted in the mapper so by not using any of those things just mention you kind of safeguard yourself around the pitfalls of mapping the third thing that people mention is performance but we're going to take a look in this video and see how this might not actually be the case now what i have here is a couple of projects and we are only going to focus on the first one and that first one is the mapping experiments at least for now so what i have here is this mapping benchmarks class where i have three benchmarks we are manually mapping an object we're using express mapping or express mapper to map it it's one of the new get packages you can use and the other one is automapper which we've already covered in this channel and you can click on the top right corner of the screen right now to take a look at that if you want to and for a bit of context i'm going to show you what's in this class we're creating another mapper i mapper class ignore this for now we're going to get back to it in a second and we are also initializing a statically initializable express mapper mapper and this is how we're doing our mapping the express mapper profile is registered here while the auto mapper is at the very bottom here and we're mapping this object the product object with these properties to this product dto object which looks exactly the same that doesn't mean that this will normally be the case usually you're mapping from a domain object to a data access layer like your database dto or to your api contract and they might look different have less properties have more properties on different places we're going to go for the very simple approach where the objects match and you have them separated because if you want to make a change on your domain object you don't want that change to break your database so you don't use the same you use a mapper to bridge between the two and make non-breaking changes safer or breaking changes for that matter and this is the object i have i'm generating the exact same object every single time because i want the test to be consistent so i won't just go it dot new or randomize the text i want it to be the mappers performance that we're measuring not any other thing and with that out of the way i'm going to run those benchmarks and see what numbers we have oh and also let me show you the manual mapping how it's done um i'm just getting the object we want to map and then i'm creating a new version and i'm mapping to a new object like this so with that out of the way i'm going to run the benchmarks using benchmark.net another package that we have covered in this channel and if you want to check that out click on the top right corner of your screen right now but with all that out of the way let's give this a second because it does take some time to run those benchmarks and in the end we're gonna have some reliable numbers so let's just wait so the results are back and if i scroll up i can see that the manual mapping is actually the fastest surprise surprise with a hundred nanoseconds second is automobile with double that time but we didn't actually write any code to do the mapping and it used the least memory and it didn't have any gen one garbage collections while the manual mapping did we're gonna see why that happened in a second and the next express mapper with the slowest now automapper gets bad rep because before some of i think it's before 5.0 performance was really bad but lately it has improved significantly and even though the mapping looks basic this is the type of mapping that you should be using a mapper in the first place for if you have complicated mapping with insane rules and on before and on after you probably should manually write your mappers and separate those heavy things outside the mapper because you're misusing your mapper so this is the stats these are the starts we have for the mapping right now what i'm going to do is i'm going to introduce you to a nuget package called mapster and mobster has a few interesting things going for it the first one i want to show you is how you can do mapping with mapster like straightforward mapping the same way we're doing it for the ones that we already have so let's build on top of what we have we're going to go to the benchmarks and i'm going to add a new benchmark and i'm gonna name this mapster adapt and i'm gonna show you why and i'm gonna name this mapster.example and or sample and i'm going to create that method and i will need to move that a bit up so what we need to implement is using mapster adapt from one object to the other now the only thing i'm going to do is say return generate product which is the product that we are going to map from and then dot adapt and then product dto and this adapt method doesn't need a profile to run it will automatically detect the incoming and the target the destination object and we'll do the mapping dynamically so i'm going to run this and again we're not using this thing that exists up here forget about this for now just have it so i don't spend much time um writing code all i have is an extension method that mapster which is a package you can find under the name mapster here version 7.0 is the one i'm using now is providing so back to the benchmarks i'm going to run this let's wait for a second and let's see how mapster performs out of the box so that is now done let's go up again and see that mapster now is not only the one that uses the least memory out of all of them but it's also the fastest out of all of them even from the mapping the manual mapping so that is weird and we'll see why the manual mapping is not as fast as we'd like it to be but it's very interesting that the adapt method being completely dynamic is able to outperform what what we wrote so that's fine but this is not normally how you would map using map store because this is a very not a rough method but it doesn't really accept any configuration at this state so what we want to do is do the same thing but provide some configuration and for that i've created this method returning some config and what i'm going to do just because i don't want to re-initialize this object over and over again i'm going to say private static read-only type adapter config which is the configuration for the adapters for mapster and i'm gonna name this uh well type adapter config that's really easy and then i'm going to statically use that here but i'm not going to use that yet what i'm going to use is i'm going to change this method to be named adapt with without config and then also add a new one with config and this will use now in here as a property the the config let me copy that because i forgot the name here you go and what config has internally is basically the same thing that you would have in automapper using the new map or admap you can have tons of rules and compiler settings and you can say apply fork scan there are many features that i cannot talk about in a single video this is more about the other features that are coming down the way that map that mapster supports but the normal thing you would do is you do new config like we do here to create a mapper and then you would have the fluent api here to do other things again with before mapping after mapping ignore if map with things that you would have or features that you would have in automap or other mapping platforms there's nothing special about it in that sense and i'm going to change my benchmarks to say mapster adapt without config and change that without config sample and then i'm going to add the other one with config but even then these are not the only ways you can use master with in fact it's not really how you will use it how you will use it in a realistic scenario is more like this you would and this i'm going to change it to adapt to type sample what you would have is you would have an eye mapper same way that you have in auto mapper so you can mock your tests and mock mockular mapper and do other things with it and then you would use this mapper with the provided config to use it in your api and i do have a sample here which shows you how you can do this if you check the code in the description you're able to check that out i'm not going to be talking about it but there are packages that make it simpler and then i'm going to use the mapster mapper that i created i'm going to say mastermapper mastermapper.from so which object i am mapping from and i'm going to say generate product so i'm mapping from that product and then adapt to type productdto and now the config is baked into the mapster mapper itself and since this is basically a fluent api you will be able to do other things with it in both mapping and config and also the way you're adapting you can fork which is another interesting thing or create a projection expression there are more advanced features that i won't be covering in this video but i highly encourage you and recommend you to take a look at it so now we have this new method i'm going to add it in the benchmarks which i am failing to click ok here we go adapt to type and i'm going to name this adapt to type here we go and now we have all the mapster like straightforward mapping benchmarks in place and i'm going to run this now this will take for me a few minutes for you just a cut but let's give it a second for you as this is running so the benchmarks finished running and i can scroll up and now i can show you that the adapt with config is now slower than the manual mapping that's because it actually uses pre-defined rules and it's not using the very straightforward dynamic and optimized way that the no config version is using and then the adapt to type which is using the quote encode proper way to do it with a from and an adapt to type method is somewhere in the middle between auto mapper and the manual mapping now you might say okay nick that's just another mapper what's the point 50 nanoseconds is nothing i might just as well use auto mower which i already use and i like that's a very fair point but here we're gonna dive into some advanced things mapster supports code generation for mappers which means that it will write the code for the mapper for us in a manual mapping way with code generation we're gonna just instruct what we wanna map two words and then mapster will technically write the code for us using code generation and we'll be able to use that in our application providing very very fast performance technically it's as good as the manual mapping performance so the first thing we need to do for this to actually work is go to the terminal of your application and i am going to have to see the into the mapping experiments and then i'm going to do dot net new tool manifest so this create the manifest file for me and then i'm going to do dot net tool install map stir dot tool and as you can see this has now been installed and this is cli utility for dotnet which will be used by the automatic code generator that will write the c shop file for us the other thing that i need to do now that i did that is copy few things that by the way exist on mobster's website and i will have a link in the description down below for you to use and we're going to edit the cs proj file and at the bottom i'm going to paste this you don't really need to know what it is but it's basically including the automatically generated cs files that mapster will create and also gives it a few tasks to do as part of build so let's close that and we don't really need to include any other package all we need to have is mapster here in new year now with that out of the way the only thing we need to do on our products to create the mapper is to go at the top of the class and say adapt to and then i'm going to use the following format just so we can have consistency name and name here defines the class name that we are in so product code gen dto and this if i build it will actually create the dto but that's not just what i want it could be you could just create the thing you're mapping to using mapster but in my scenario i'm going to also say generate mapper and i need to do that outside of this so generate mapper and now when i build let me show you what happens so if i if i scroll here and show you a few things have happened the mobster tool was installed and restored and then it was run for both model extension and mapper which means that the models folder now exists what is the models folder the models folder is where mapster will automatically put the things that it generated the models and the mappers so first let's take a look at our dto oh look we didn't write anything but we have our okay i missed one the product variant should also have the exact same rules so let's go back to the product copy that and then go to the product variant my bad and do basically the same thing add the exact same mapper on top of it and push that forward and now let's do this again and now we have the proper generated code option here because we do have the adapt2 attribute and we have a mapper for it a mapper that we did not write it was written automatically by mobsters utility and same thing for the variant mapper and same thing for this so let's take a look let's make a benchmark for that and let me show you how you can map using the cogen version of mapster so now let's just take a look at how we can benchmark this and how we'll do a mapping like this so we're going back to the benchmarks and i'm going to add a new benchmark which is mobster code gen and then mapster code gen sample i'm going to create that method and i'm going to move it up here we go and what i want to do is i want to say return and then the object which is generate product dot and then as you can see in the bottom we have a few new exceptions one of them is adapt to code gen dto this extension i think i said exceptions before sorry i meant extensions has been automatically generated for us and i'm going to return that of course we cannot return the same product dto because now we're mapping to a new ddo so product code gen dto will be used here and we don't need any settings or anything because all those settings are baked into the code that has been already generated for us so back to the benchmarks i'm going to change that to product cogen dto and again we have a mapper without writing well actually with writing just a single code which is the attribute how amazing is that i'm going to run those benchmarks now and let's see what we get at the end so benchmarks has finished running so let's take a look at what we have oh interesting so mapstress cogen is 50 milliseconds mapster than my manual mapping that is very interesting so i'm sure that i didn't write the best code i could in my manual mapping and we can optimize that and i'm going to show you very quickly how we can optimize that but the best performance you can get out of the box and then customizing with a few attributes if you want to and get that that's amazing this is truly amazing a very interesting proposition if you just want to do very simple mapping which is what you should be doing really anyway but let's see how we can optimize our own mapper before i wrap up this video so what i have in my manual mapping sample is i did the dirty thing of using link and which is not as performant i mean again this whole thing is on the scope of nanoseconds which is one millionth of a millisecond so this is probably not your application's bottleneck and if you're using automapper you're going to be fine but if you want to support a project that is doing something really interesting and could be something way more than it is right now take a look at that check it out i highly recommend it from what i've seen until now so let's optimize this a little bit what we have here is i'm gonna create a dto here and i'm not gonna attach the options yet so i'm going to leave that empty and then i'm going to say more options equals new list of product variant dto and then i'm going to say for uh what we have here product dot options dot length or count that's that's fine and i'm going to change that to a var and then i'm going to say options dot add wait a second why don't i have a forage loop oh because four is marginally more performant i think i could be wrong with that but i think that's the case at least it used to be so let's use that if i could type so product dot options do a read and get the id and then the same thing for color and size so size and then also color and with that small optimization i'm going to say a dto dot options equals options and i'm going to return the dto so that should perform better i'm going to run those benchmarks again and let's see what we get so here we go all the tests have completed all the benchmarks and as we can see my code is still not as performant as mapster's automatically generated code so i'm sure if i dive more into what i wrote i can optimize it but at that point i'm just wasting my time i might as well just use mapster and again this is not a video showing you all the features that mapster supports this is just familiarizing yourself with mapster and giving you a motive to go and check it out and learn more about it if you want a dedicated video on its feature set and the mapping capabilities i can do that in the future but for now we're going to leave it here that's all i had for you for this video thank you very much for watching special thanks to my patreons for making these videos possible if you want to support me as well you're going to find a link in the description down below leave a like if you liked this video subscribe for more content like this and ring the bell as well and i'll see you in the next video keep coding
Info
Channel: Nick Chapsas
Views: 102,801
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, asp.net, .netcore, dot net, core, C#, how to code, tutorial, asp.net core, js, csharp, rest api, lesson, dev, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, asp.net core 3, .net core for beginners, Mapster, the best .NET mapper that you are (probably) not using, Mapster mapper, Mapster .net, .net mapper, c# mapper, automapper, expressmapper, mapper, contract mapping, domain mapping, dotnet, .net
Id: UIslFVEHkzA
Channel Id: undefined
Length: 24min 1sec (1441 seconds)
Published: Tue Jan 05 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.