 Hi, welcome to Visual Studio Toolbox. I'm your host Robert Green and joining me today is Julie Lerman. Hey Julie. Hi Robert. Welcome back on the show. Great to be here and we're in the big studio this time. I know, isn't it awesome? Yeah, it's nice. We're going to talk about some entity framework today. Yeah, and a little fun with Visual Studio 2017 at the same time, just because I can't help myself. Cool. But any frame are core. Any frame are core. Yeah. OK, so for the viewers who are still confused on the difference, entity framework, entity framework core, what's going on? Well, we've been working with entity framework through entity framework six. Entity framework core is the new version, but it's not entity framework seven, although they did originally name it that for a short while. But it's really a lightweight cross-platform version of entity framework. So entity framework is going to continue on its path, although all the real innovation will go in EF core. Entity framework six will continue to be paid attention to and updated and take pull requests and bugs fixed and all of that stuff. And with all its big, rich features, and as Rowan Miller has said on Channel 9 before, it is battle tested. And EF core is new. So EF core can be used with just full .NET framework, but it also has the ability to go along with .NET core and be cross-platform. OK, so if you're already building an app using entity framework, you should continue using it. Yeah. No reason to toss out everything and start to scratch. There rarely is. And it's not just an update as entity framework has been in the past. OK. And if you're building with .NET core specifically, ASP.NET core or a multi-platform application, you would certainly use entity framework core because that's what it's designed to work very well with that. Yes, and also with UWP. OK. An interesting thing is if you're using ASP.NET core because you really love the features of ASP.NET core, but you totally plan only to deploy to Windows, so you don't need the cross-platform stuff. In that case, if you really want to, if you already have maybe APIs you've written with the EF6, then it is possible to mix those. So you can have EF6 with ASP.NET core, like just in their own assemblies. So you could use entity framework core from a .NET 4.6 app? Well, that's backwards. No? Yes, from 4.6. So you can use EF6 with ASP.NET core. You can use EF core in full .NET Windows only applications as long as they're, I think, 4.52 or above. So WPF, Windows forms, ASP.NET web forms, as long as you've got that framework. But you can also use EF core if you're doing full-blown .NET core targeting cross-platform. Right. Okay. Well, it's important to be really, really, really clear about that. Right. That makes sense. All right. So we're going to talk about entity framework core today. Correct. Excellent. And a little bit of .NET core, and a little bit of .NET, and a little bit of everything actually. That's the cool thing about EF core, because you can use it on Windows, and you can also use it anywhere that .NET core runs. So we're going to be all over the place for a bit. So the first thing I actually want to show you, because I am excited to be using the latest release candidate of Visual Studio 2017, along with the new tooling. You must have had these conversations also about how when you're focused on .NET core, the project JSON support is shifting back to MS-Build and CS project. So people who've been already working with .NET core and EF core and using projects that were the metadata, so to speak, is the project metadata is in project JSON. If you, in order to move up to these newer building tools, there's ways to migrate projects. So of course, I had to check that out. I've got solutions that have .NET core, and EF core in them, so I wanted, and using project JSON, and I wanted to bring them up. So I'm going to take the same project and I'm going to migrate it two different ways. Okay. Okay. So first, I just have to grab the project, and first I have to see. I don't mind looking at you in your blurry, but the computer screen I got to see. I got to see. That's my best side. Yeah. So I have a, this is a project that uses, that I, it's an EF core ASP.NET core project that I built in Visual Studio 2015. And if I go in there into the source, you can see evidence of that because I have Xproj and I have project JSON. Okay. Okay. So now I'm like, I want to use the new, the current, the coming, it'll be current at some point soon. So I want to move to that, but I've got this project JSON, how do I turn it into a CS-proge file? So the migration tools do that. So the first thing I'm going to do is I'm going to take this project, I'm going to copy it. I'm on a Mac, you may not be able to tell, but you may be able to tell. So I'm going to copy this into a shared folder on this computer. So here's my shared folder and I'm just going to paste this. So there's the Xproj. Now I'm going to go back over, now I'm back over in the Mac. So I'm moving back and forth from being an OSX, which is where I am now. Over here, I'm in a virtual machine, that has Windows 10 running on it. So that's also there. So here's the new Xproj folder, right with all the stuff that I just showed you. So what I'm going to do is I'm going to go right out to the command line. Right, I'm going to use .NET Core command line tools, and I'm using the newest command line tools, and this is actually easier on Windows because I can just type CMD in the toolbar, which is something I only learned a week ago. Did you know you could do that? Yeah. That's like there was a big Twitter storm about everybody going, oh my God, I didn't know you could do that. I was one of them. So anyway, I have to go out to services and new terminal tab at the folder. So here I am now in, so here I am now in, I'm going to just zoom, not that way. You're going to edit this part out. We don't edit on this show. You're lying. Actually, we almost never cut anything. All right, I was going to increase my screen, but my font, but I haven't done that in so long, because I'm really truly a Windows developer. So I'm still a little dorky on my Mac. Anyway, so here I am in that project, and there you can see some of that evidence. There's the source and my Samurai tests and everything. I'm going to go into the source. Actually no, the solution, my solution, my solution file is here. There it is. My solution file is here, so I can do this right here. So just first of all, I want to show you I have .NET running and I'm just going to do now .NET-Version. So you can see that the version, this isn't the version of .NET, this is the version of the SDK that I'm using. So it's preview four. If I say .NET help, there's a few new commands in the tools, the .NET CLI tools that we didn't have before. One of them is migrate. So I'm going to clear the screen. Wow, I really cleared the screen. There it is. Now I'm going to say .NET migrate. Now what's going to happen is it's going to see the solution folder, read it, find all the projects that are in the solution, find all of their .NET core. So they all have project JSON, they don't have CS projects. So it's going to find all that stuff and it's going to convert it to use the new stuff. I just can go have a cup of really, really fast cup of something. So it has now migrated the projects. Now again, if you haven't done any core projects and you started today with the latest build, you don't have to do any of this stuff. That's right. Because we're already back to CS project. Which means if you've never done it before, nothing's ever changed and you don't know what we're talking about. So there's an important thing to know about that, which is that won't work. You can't use the new stuff in Visual Studio 2015. There's not going to be tooling in Visual Studio 2015 to use the new stuff. So if you want to use this newer stuff, you'll either move to Visual Studio 2017. There's the community edition or Visual Studio code. Or Visual Studio for Matt. Right. So all of those will be able to support the new tooling. Okay. But Visual Studio 2015 won't. And as a matter of fact. But 2015 would continue to support some version of .NET Core? Project the one. Previous version. Okay. With the project JSON. Yeah, and you could do that with Visual Studio code too if you target the older SDK. But you wouldn't be able to open the same project in both 2015 and 2017. No, as a matter of fact, yeah. It depends on how things are structured in the .csproj file. Okay. All right. So I'm not going to spend, dwell too much on that. I'm going to show you some of this just because this is kind of cool. Yeah, I don't want to hide that. And to take away the fear. Well, that's why I want to show it to you. It's interesting, right? But take away that fear of, especially for me. I've been using EF Core, I've been using Project JSON. Now I'm going to be moving to the new stuff. So even though I'm not like ASP.NET Core person, right? I still have to deal with this. Right. So anybody else is in my shoes is going to see that. But if you're brand new to anything core, then you just file a project and go and everything's fine. Yeah, yeah. Okay. So while I'm on the Mac, I'm just going to open this project up in Visual Studio Code. And I can do that by typing code space dot. And it'll just open what I have here. It's just so we can take a quick look at what we got. So it created these csproj files for my different projects. So here's the data project. And it created csproj file. It's XML now. And here are how the package references are. Actually, that one becomes redundant because of the tooling. We have this up here, this SDK. So we don't even need that. Again, it's all fascinating to me. I want to explain it all. But the point is Project JSON's not here anymore. It can took all of what it needed. You can see, there's my references to my other projects. There's my entity framework core references. So it's fixed all that up. And it did create a backup folder and tucked the project JSON files away just to the stuff that they got rid of. They tucked that away. So you have access to that. And then presumably if there's errors, it would show you errors somewhere. But there weren't because it was so easy. Of course not. Yeah. All right. So now back over to. This thing's almost ready to go. Of course there aren't errors. Now, OK, I'm still on the Mac. OK, oh, back to Windows. Here I am in Windows. So remember, this is the one I just copied onto the shared drive. I don't want that one anymore. So I still have this one, the original one that I copied. And this is the one, again, came from Visual Studio 2015. There's my solution file, my source code, and there's Project JSON and Xproj. So what I'm going to do here is I'm going to open up a new instance of Visual Studio 2017 RC. And that won't take a few minutes. It says that, but it's fast. It can take a few minutes. And I've got three instances running now in a virtual machine. So that's pretty nice. So now what I'm going to do is I'm just going to plain old open up the old solution that came from Visual Studio 2015 that has all the Project JSON stuff. Uh-oh, I have to find it. I know it's on C. I put it on an easy place to find. C, migrate tests. There it is. Phew. OK, so there is that. Right, that's the solution. I'm not faking you out. That's still the same one we were looking at. So I'll go ahead and open that. You're faking a lot on this show. I don't know about the other shows, but I'm faking. There is, whoa, we noticed something, right? It's a one-way upgrade. I think that's very, very clear. It discovered all four projects that are in there with their xproj. And it's just saying, we're going to go ahead and do this. And there will be a log file, all right? So it's going to do the same thing you just did in a. Right, and I didn't even have to know that it's going to do it. When I was in the CLI, I needed to know I needed to migrate. I needed to know I wanted to migrate. Here, I'm just like, oh, I've got a new version of Visual Studio. Yay, right? I want to keep working on my .NET Core projects that I've been working on. I'm going to open them up. And it's just going to go, oh, we're just going to do this little thing for you. Don't worry about it. And now you'll be able to use it in here. Plus, you get the new tooling. So there it is. Do you trust it? Is it a trustworthy source? Because it came from the internet. This is opening up the log. Now, there is one note here that it had to make some changes, non-functional changes. And rather than reading it, it's just basically saying that it made some different references in the solution file to the new CS Proj files. Now, there are also some warnings here. And this one is just because my project was not using the most latest, greatest, greatest, greatest Entity Framework Core tools. And it's just saying, you had Preview 4, and we're going to give you Preview 4 final. And all those tools are still in churn. So that's fine. But the other interesting thing is that the CS Proj files are smarter than the Project JSON. In Project JSON, I had to explicitly say, I'm using that standard 1.6.1. Here, it's saying, you have that package reference, but you actually don't need it because with a new format, we have this .NET SDK tag on there. And that will go ahead and pick the right thing up. But at this point, it's just saying that, but it didn't do anything about it. But I could just go in there and modify that. And that's all the other error messages. They're not even errors. They're just warnings. It's in there. It's basically going to get ignored because we already put something in there that's going to take care of it. So, well, we're on Visual Studio Toolbox. So Toolbox just wanted to show. It couldn't help itself. Very appropriate. Yeah. Why are you all here? Just go like that. Thank you. So here it is. Now here's something else pretty cool. So I've been using Project JSON. Like before .NET Core, if I wanted to look at what's going on, what references or anything are in a .NET project, I would expand references. It's actually listed a little differently in here. Instead of just references. Or you'd go out to Windows Explorer and open up the CS project file as a window pad or something. Right. Or I would just look at what references I have. Now what you're seeing here is that because we've got to, it's actually making it easy to differentiate what we're getting from NuGet and what we're getting from project references within the solution. So that's why that looks a little different. But with that project JSON, I really got, even though here now, I can use package manager console. I can use add reference and get that UI. I can go out to package manager console. I can just use package manager. I just want to edit. I liked it. We really liked it. And it gave you intelligence on the latest versions of libraries and whatnot. Yeah. They should add that to Visual Studio. Well, look at this. Wow. So if you wanted, what did you have to do? If you wanted to edit a CS project before? You had to unload the project or go out and do all this stuff. Now you can edit the CS project. It would be cool if you could just right click and edit. Yeah, there you go. Now you can't, right now, you can only do it in .NET Core projects. Once I started doing this in the .NET Core projects, and then I open up Visual Studio 2017 to work in .NET Framework projects, I go and I start, I right click and it's not there. I'm like, no. So we might get some more parity along those lines. So it's the .NET Core. Yeah, it's like I learned something and then I have to unlearn it. But I liked being able to do this. And this is editable, I assume. It is, we don't have all the intelligence yet. So it's really frustrating. And I know there was a lot of, and I participated in it, I'm sorry. A lot of moaning and groaning when we were told, sorry, we know you love Project JSON, but we're going back to CS project for very good reasons. Because I really liked that. I was like, I don't want to go XML, blah, blah, blah. So having looked at this and knowing that the intelligence and the help of the package references is coming, that they're just working on it still, I'm okay with it. Because they've actually streamlined CS Proj enormously. Like that's it, that's all that's in there, really streamlined. So here's that SDK attribute up here, right? That makes this one unnecessary, right? You know, we'll work all that out. And maybe eventually the tool will go, yeah, I don't need that, I'll get rid of it, or comment it out. So just in case you really explicitly want it for a different reason. So it just did all of that for me. So now I can take my .NET Core projects that I was working on in Visual Studio 2015, Project JSON, and very easily move up to being able to use the new tooling. And you know, Entity Framework, Core came along for the ride, right? Well it's important to me because I'm using EF Core, so I'm using all that stuff also. So I'm going to close this project and then what I want to do is just show you some cool things about Entity Framework, Core. Okay. And yeah, my idea of cool things might not be the same as everybody else's, so this isn't going to be like the standard, not necessarily the standard features that everybody always highlights, because we can see those. You know, we get exposed to this a lot. So as I'm learning things, I'm like, what was some stuff that not everybody knows. I can do that? That's really cool, right? Oh, that makes my life a little easier. So even though I have these numbered, I'm going to be, I'm going to go against my ADD green. It's going to be really hard, but I'm going to do things in kind of a different order here. So Entity Framework, Core has a lot of familiar things from EF6, you know, the basic ideas. We've got the DB context and change tracking and DB sets and a lot of the interaction. It should be very much the same. But there's all, some things are going away totally. Like, you know, we're not going to have the EDMX anymore, which, you know, some people are like, so what? You know, like I never used it, I always used code first. But, you know, there are a lot of people who have been using the designer and really dependent on it. So there's actually third party support for EDMX and being able to work in a designary way. That this EF core isn't going to support it directly. So the first thing I want to show you that's new and cool, that made me go, oh my gosh, is the fact that Entity Framework now supports mapping to fields. So in order for Entity Framework to comprehend the model, and more importantly, in order for Entity Framework to be able to populate classes after you've done a query and it's populating objects, creating objects with the results, it was able to map to scalers, properties that were scalers, and properties that were collect, like your navigation property was a collection. So this was a problem for people who really, like I do a lot of domain driven design and I'm really a control freak about how my classes are designed and how people, how other developers or myself even, are able to interact with the classes and encapsulating fields and protecting them so that they can only be used the way I want them to be used, fields and properties. Anything in my class is really important. So one of the ways to achieve that when you're not thinking about Entity Framework is to expose the fields and then you can encapsulate the properties and interact with that. But Entity Framework wasn't able to map to fields, it could only map to properties and eye collections. So there was a way, if you just had a scalar property, there were ways around it, but we can now map to a backing field. So I don't have before and after here, I just have how it is new. So for example, I, in this Samurai, and I have to give you the origin story of this domain, when any Framework 6 came out, I kept calling it the Ninja Edition. And then when EF Core was originally called EF7, it made sense to me to go to Samurai because of the seven, you know, we first Ninja to Samurai and also there's the movie The Seven Samurai, which is a favorite movie of mine. So now that it's called the EF Core, I'm just sticking with the Samurais for now. So that's the origin story of my Samurai domain. And so since it's a movie, we have quotes, right? So what I want to do here in terms of encapsulation and saying, you know, I don't want people to just willy-nilly modify properties. If they want to modify properties or set values to properties, they have to do it under my rules, right? I'm setting the rules. So you're allowed to specify the name of a Samurai when you first create a Samurai, when you instantiate one. But notice, I've named this immutable name just to make it really, really clear. So there's the name property, right? And all the name property does is return this variable, right? So you can't say immutable name equals Robert. You can't code against that. I've said the only way you can set a name is when you're first instantiating this. So this, what I'm able to do now is map to that backing field. An entity framework actually does have conventions that will discover things by itself. So for example, if this was just called name, and then it couldn't find, but there was no setter here, it would see this underscore name and the convention would be able to assume that that's what it should be mapping to. But there is a way to, because I have something different, you can specify it. So I'm gonna go over to the context where I've got Fluent API. That's the wrong one. I got a few of them. There, where I've got the Fluent API. And I'm saying here specifically, the property called immutable name has a field called underscore name. So now entity framework will comprehend all the way through from migrations, creating the database, understanding how to interpret link queries into SQL and understanding how to take results and push them into objects. So it will understand that. Now I wouldn't have had to do this if that property was also called name because the convention would, the convention would figure that out. So that's actually something, we had a way to get around this before, even though we couldn't map to the field, there was ways to do that. But what we couldn't do, where's my samurai? What we couldn't do is protect a collection. That was really frustrating. So you could add in methods here to say, hey, if you want to add a quote to here, you have to go through here because I might have some other important business logic inside of add quote to make sure you're doing it the way, the things that I need to make sure of are happening. There was no way to do that. One of the reasons was originally up until now, entity framework does not recognize, so this is a standard coding way for getting entity framework mappings again. A standard way to do that protection is to make the property an innumerable and then nobody can edit an innumerable. They can't add another sword or add another quote into that innumerable. But entity framework didn't recognize that. Entity framework did not comprehend innumerables and couldn't map to them. And now it can. So now I can protect this so I can make the swords property, navigation property innumerable, which means entity framework when I do queries, entity framework will be able to populate it because that was the problem, right? But at the same time, I'm able to stop anybody from adding and removing from there without using my methods that I've defined, my control freak methods. Because I'm a control freak. So there is, I learned this last little bit from a great blog post by Arthur Vickers who's on the team. He's got a great blog at oneunicorn.com and he's been blogging a lot of really good detailed stuff about EF Core. So one of the problems with this is it's still possible for somebody to kind of work around this, get back call swords and then get the results of this, which will be this and then cast it as a list and then change, they can do all that kind of stuff. So there's another way and this is going to get more smoother to do in a future, like I think the next version of EF Core. So this is EF Core 1.1. So there's this cool trick of what's, it's referred to as a defensive copy. This was something new to me. I guess it's, once again, because I was a history major, not a comp sign major. Have you ever heard of a defensive copy? I was an economics major. I didn't do comp sign either. All right. So a defensive copy is a way of having, returning a copy of an object instead of the object itself to make sure that nobody touches the actual object, okay? So here's an example of instead of, so here, I'm using iEnumerable, right? And I'm going to return quotes anytime somebody asks for quotes. I'm going to return underscore quotes. But instead of returning underscore quotes, I'm calling two lists on it. So that's actually creating yet another object. So even if they do muck with it, they're not going to really muck with my own sorts, okay? To do this, you have to add some code here, right? Some code here, right? So this is this property, set property access code. Notice I'm not even using Fluent API. I'm going all the way into the metadata to do this, okay? So that's what will get smoother. It'll, there'll be a Fluent API way to do this. So this is more a matter of, you know, find my demos or find Arthur's blog posts and copy and paste to get that working for now. But what this does is even if I didn't have this and I ran migrations and created the database and inserted data into the database, all that would work. It would still find everything. This is about getting the data back. And so it, like if you do a query, I could run it. I actually, you know, have real code here. I could show you the difference. So here's just a little pro, little tiny program that instantiates my context. I'm just tossing and recreating the database to, you know, because it's a demo. I'm creating a new Samurai. I'm adding a quote. I'm from Vermont, so, you know, Eat More Kale is a good quote. I'm adding a new sword and giving it some value. Adding this graph now to the context and calling save changes. And what I want to do is show, if I take out this code for now, when I go and run this, so I save the changes and I say, okay, the changes are saved. I spin up the context again and I do an eager load of that Samurai. Give me the Samurai, the first Samurai, all of that Samurai's quotes and all of that Samurai's swords. And then I iterate through. Tell me the name of the Samurai. Show me the name, show me the text from all the quotes. There's only one. Show me the weight of all the swords. There's only one, right? So if I run this, I don't trust my control S and on that Mac keyboard when I'm in Windows. Sometimes they just do different things. So if I run this and I'm just gonna do debug, start without debugging and spit it out to the console. So the changes were saved. Notice I didn't get any quotes. Quotes is the one that I protected with that defensive copy, but I did get the swords. So that's showing me that the innumerable mapping on its own is working without having done the super special thing, right? So just to get back to the program, right? Added, right? This was the quotes. If I go back over to the Samurai, the swords, we saw the sword. The swords is the one that I just did, the plain old fancy new innumerable mapping. But this is the one that I was doing the defensive copy. So in order for the defensive copy to work, I do have to specify this in the context. The data was in there. I've actually looked, opened up. Oh my gosh, you've done, I think you've done a show with Eric Iskav Jensen who does the SQLite and SQL CE toolbox. It already works in this version of Visual Studio 2017 RC. So I'm using, I was using SQLite. So I looked and I like, the data definitely got in there. So it was the lat, when this was commented out, it wasn't preventing the model from being correct or the data from getting into the database. It was just preventing the model, the query from populating the data with the results. So the results do come back, but it just can't get them into the class. So now that I've uncommented it, and I guess I've saved it, I'll just run it again. And this time I should see the sword and the quote. Cool. Okay. Did you have your kale today? No. Sorry. I've not had kale today. Anyway, so in my typically nerdy self of, oh my God, this is the coolest feature. I could just talk about this one feature like all day because I think it's so cool. So there that is. So that all comes under the guise of field mappings. But for me, the beauty is I can now finally truly encapsulate collections in my classes. And I'm really happy about that just in case you didn't notice. Oh, here's something. I actually looked, I knew I had put issue in on Codeplex when EF5 was on Codeplex and EF6 was on Codeplex. But I think this, I looked this up. This is something I asked for five years ago. It's been in here since the first release of EF1 but I didn't realize it was there. I finally discovered it one day. I was like, you know, I was kind of trolling through the source code and I went, what, what? So the ask, as you say at Microsoft, what's your ask? My desire was to be able to define a DB context as read only. The reason for that is when you're doing queries, when you're doing queries with entity framework by default, entity framework keeps track of all those results. It assumes, it assumes that's what you wanna do is keep track of the results. So in order to do that, it builds, as it's pulling the queries and pulling the data back and creating your objects, it also creates these other little change tracking objects and keeps track of the state. And that's where it knows it's been added or updated or deleted. And when you call save changes, what should be sent to the database. Okay, so there are plenty of scenarios where you don't need that. You're not gonna be using it, whether it's read only but more typically if you're doing, like you've got a web API or a website or something. And once you've made that request, the DB context goes away. It's not gonna be, you know, it's just, you're using the DB context on the server to do a query. It's sending the results down the wire to your UI or whatever. And the DB context instance, that all of that stuff goes away, right? The request, the DB context, all of that stuff goes away. So in essence, what it's doing is you're querying the data, it's creating, spending all of this time, all of this resources, creating those change tracking objects, right? Maybe not so much depending on what you're doing, obviously, and then throwing it away. So what we've always been able to do in one form or another, the terminology changed as we evolved through different versions of an entity framework, was to be able to say, hey, this query that I'm doing, I don't need you to create those objects. And the way we do that is we append, let's see if I got a query here. Here's a query, so we could always do that. We could say as no tracking, right? So we could say that query, don't track, don't create those little tracking objects, right? But you have to remember to do it all the time. And if I'm creating a web API, I wanna do that for every single query. And I have to remember to do that for every single query. So I said, can't I just say it for the DB context? And now we can. Yeah, cool. Long story, right? But I wanted to give you some context. So this actually, I could show it to you here if I'm debugging. So I'll show you what the default is. And so I'm gonna just run this again and I've got a break point here. But this time I'll debug it. Hopefully I don't have any other break points. Okay, great, it's at the end. So what I'm gonna do is look at the context itself to see what it's tracking. And I'll go to quick watch and context change tracker. And just trying to find the most efficient way to see it, state manager. The state manager is what keeps track of those little, those state objects. So it's got three, right? For all the things, right? Just assumed I wanted them. So what I can do now rather than, well, that was just one query really. So it is kind of easy to do it there, but the point is I don't want to have to remember to do it on my queries. So I can go back to my context and I can do it at any time actually. So I can literally define any time you use this context, change tracker, query tracking behavior equals, got two options, the default, which is track all and no tracking, right? So I can say just blanket this Samurai context no matter what you, you know, unless you say otherwise. So you can track, can you turn it on for an individual query? You can because now we have as tracking. Okay, cool. For the, on the query. So this is changing the default for any query that is done on this context. This one. Right. I could even, maybe I don't want it to be blanket for this whole context. Maybe I want to say, you know, I'm using this context in a few different places and in some places I need it to track. When I'm using it here, this place I'm using it here, I don't want it to track. So I could specify it on the instance. Well, I was specifying out on the instance before but I could specify it on this instance. So that's the change tracker query tracking behavior. I could do it there. Okay. So I just want you to see the difference. Remember when I debugged it before because I know you believe me. I know I can always get away with that. You believe me, don't you? Yeah, I have to see it. I don't believe me. I always have to see. This is how I know how things work. I like to know, I like to look and really see what's going on under the covers. So going back down to into the change tracker, into the non-public members, into the state manager. And oh, oh, I took it out. Remember when I took it out? Did you see me do that? See, that's the downside to proving things. Look. Okay. Because you discover that you're dumb dumb. That's what I usually discover. I'm a little bit of a dumb dumb. Oh, right. Yeah, and this is the show where you don't edit. You're not going to cut that part out and make me look better? That's like when you get talking to the .NET Rocks guys and you tell them a dirty joke and they're like, don't worry. It's going to get cut out. Or you're like, you say something. You're like, that's not for public consumption. Oh, wow. The only thing we cut on this show is if I do swear accidentally. If you swear accidentally or if I swear accidentally, or if you said something you weren't allowed to say. Oh, right. Like ship dates or something. Or if the demo was so completely harked up that. How's this going so far? Fantastic. Okay. So there, zero. Or if my phone rings. Oh, you didn't turn it off? For the longest time, and I've told the story before, so bear with me. For the longest time, I thought it'd be cool if my phone rang during a taping. And then it did. Cool in one way. It's funny. And then, so I left it in. I thought that was funny. And then it happened again. And it was sort of humorous. Now if it happens again, it's just annoying. Right. Leave your phone at the door. No, actually it's still in my pocket. I haven't turned it off, but nobody calls me. Anyway, so, tada. There it is. Nobody calls you. I'm sure people call you. All right, what else is exciting? Oh, the in-memory provider for testing. That's really, really cool. Are you familiar with this at all? I've heard about it, but refresh my memory. Okay, so the in-memory provider. So, have you ever done written unit tests? Sure. Yeah, have you ever written a unit test on something that really isn't a unit test because somewhere down the, somewhere in there it's making a database call? I have written unit tests for things that make database calls, yeah. And you're going, why did you say that's not really a unit test? That's a difference. That distinction is a different conversation. Anyway, so one of the things, sometimes you really want to see what's going, you want to test what's happening in the database. There's no question about it. But sometimes you're testing something else, maybe you just want to make sure that your web API, your controller method's working. And somewhere in that controller method it's doing a save or it's doing a query. And that is not really the point of what it is that you're trying to test. So whether or not it actually interacted with the database is not really the point. Or sometimes, what if something's wrong with the database and then the test fails for the wrong reasons? So you can use mocking frameworks or you could use interfaces or whatever. Or yeah, absolutely. So yeah, mocking frameworks, yeah. So we've been able to EF from just say, trust me, it works. We'll let the users find out if it works or not. Three jobs later, three careers later. So you're learning good guidance here too, for things you shouldn't do in your career. So we've had the ability to build fakes since earlier days of entity framework, I think EF4, we were able to start doing that. It was hard and there was a lot of stuff to implement. Then with EF6, they made it easier to do mocking but still setting up mocking, there is a lot of setup to do, right? So what they've done, they as in the entity framework team was they created in addition to the SQL server provider and they also built the SQL lite provider and there are also third party providers like there's one for Postgres and there's one for SQL CE and everything. But they created an in-memory provider. So it's not a database, right? It's a, but you point to it, you tell instead of saying the provider that I want you to use entity framework is SQL server, right? Or in this here, you're saying the provider I want you to use is just going to happen in memory, right? So it's really lightweight, you don't have to depend on a database and it's so easy to use because it kind of does a lot of the magical stuff on its own, but it's not mocking. So let me just show you what it looks like. So first of all, if you've got a project that's tests, you don't need to reference SQL server, right? You don't even need to make references to those things. So what I've done here is just the package I installed is the entity framework core in memory, right? So I don't have a SQL server in here at all. So I have unit tests. Now you've seen probably you may not have noticed it a lot. There's a number of ways to let the context know what provider you're using and if it's a database what the string is. I just hard-coded it in here for demo purposes, right? So it's just hard-coded. But another way to do it is to pass in the information about the provider and the connection string. That goes to for a DB context, an entity framework core, that comes to the context by way of something called DB context options. So here's the DB context, here are the options I want you to use. The option, for example, the provider, connection string, like if it's a database provider. So I'm now going to be focusing on this context. It's just a little different. That one, the one I had for the mappings was set up so I could really show you the mappings. So this is a little more generic. So the thing to notice about this is I have two constructors here. I still have to have a parameter-less constructor for an entity framework, an entity framework core. But I also have a constructor that takes in a set of those DB context options so I can pass them in. So I don't have to define it upfront. Although if you look down here, I'm doing something, again, it was just in order, it was a way to show something else about EF Core. What I'm doing here is back to how I was kind of hard coding the provider and connection string in earlier. I'm hard coding them in here, but I'm giving myself away. So this is like, this is the default. This SQL, you know, this SQL server provider. I'm going to use using SQL server and here's my database. That's my default. But notice here, and this is part of the DB context. This is not my own method. So it takes in the options builder and notice this is configured. So I'm saying, if the options builder is coming to me already configured, use that. But if not, this is a not, if not, use this. That's how I get this, the default. So I'm giving myself here a way to pass in a pre-configured options builder. So over in my test, that's what I've done here. I've created, oh, I'm sorry about the highlights. They, we need them, but not when you're trying to do a demo. They're like, go away. All right, so what I'm doing here is I'm instantiating a builder all on my own, right? And I'm saying, since I have a reference here to the in-memory provider, this is an extension method. Use SQL Server is an extension method that comes by way of the SQL Server provider being installed. And so there's other ones. So I have that installed, so I can say use in-memory database. So that's really, in-memory database doesn't need a connection string. So that's all it needs to know. So now this is a builder. And once you have a builder, then you can pass in options. It's options. And so that's what I'm doing. I'm instantiating the context and I'm passing in the builder options. So now the context, when I get there, and I can debug, I can debug it so you can see, because debugging is so much more interesting. So I'll just debug it so you can watch what happens. Actually, I wanna run it first. So let's just say, so now you see how I'm letting it know to use this in-memory provider. So to do this all in-memory without a database. So now that I'm doing that, I'm just writing regular old, any framework code. I'm creating a bunch of Samurais. I'm using context.samurais.addrange. So I can add all of those. I'm saving the changes. I'm spinning and I'm even, now if I just said after save changes, okay context, how many Samurais do I have? And it says three, that would not prove anything because it's just looking in that context. So I'm spinning up a completely new instance of the context and saying, go do a query against my in-memory provider and tell me what's in there. So it's persisted, but it's persisted in memory without a lot of extra crazy code. So what I'm doing in this assertion is- And it's persisted for the session of Visual Studio? Yes, the application lifetime. And what I wanna do after I show you this is flip over to, because that actually also creates some problems. The application lifetime. Well, application lifetime, so the definition of application lifetime is a little different when you're talking about tests running a test runner. Okay, so if you ran that again with those three Samurai be in there. So if I, if I, so you wanna see, you want, I'll run it through first and then we'll talk about it. So what I'm asserting is just that the three Samurais are there. Okay. I should have made seven, it would have sounded better. And then the other thing is just to prove that they're not, that not only do I just have three Samurais, I even have, you know, Samurais with those names, right? So if it's gonna pass and then it's gonna spit that out. So I'll just run this up there. There's a couple ways I can do it, but I'll do it from here. And then I'll go to the test explorer. There's the test explorer. So it passed and there's actually some cool new things about testing in Visual Studio 2017, but I'm not gonna show it. And oh, it's showing me the ID. It looked, right, the second thing is kind of, that was kind of a stupid what I did with the outline. So it passed and it said, yes, I've got three Samurais. And then I said, tell me the ID of the Samurai named Samson. And that was two. So it's definitely doing that. Now it's gone, right? So if I ran it again and I didn't do this part, right? That would fail, right? It's gone, I'm done. The application instance isn't running. So it's application lifetime. Yeah, cool. However, that creates some problems. How are we doing for time? Cause you know, I could just go on and on. We're getting close to an hour. Okay. Well, this is actually important because I've really had to, why is that, maybe it won't be showing it. Hello? Hello? I'm just gonna, okay, that's good. That's happy. Going back over to this other instance. That's not happy. Yeah, that's weird, isn't it? That's cause I've just been doing too many weird things. All right, let me just open it up again. Oh, yeah, not responding. That's probably just me, right? It is still pre-release software. Yeah, it's an RC. And we gotta do this too. Bang on it, bang on it, bang on it, do weird stuff. And believe me, anytime I've ever, they've gotten some nice dump files from me. Okay, so here are some more tests. I've got a, this is a constructor here. There's just another set of tests in here. So this just a different little solution. It's actually this solution that I migrated. Okay. Say that was the solution I was working in. So I have my domain classes. I've got my context in here. This is, oh, this isn't the solution I migrated. Look, this is entity framework core in just plain old .NET, no .NET Core, it's a WPF app. Okay. Yeah, but that's not where we're doing here. We're in here for the test, in it for the test. So here are the tests right here. So I'm doing a few things here. My first test is one that really does interact with the database. Now normally if I have tests that I, integration tests, I really want to hit the database. I'm not going to have them in the same test class as the lightweight test. Cause this is a, could be a slow and cumbersome test and it will slow everything down. But I just have them all in here just cause, you know, I just want to show you all this quickly. Quickly in my way, that is. So this is a test just to prove that the database interaction is working as I expect it to do. So I'm using SQL Server, right? There's my SQL Server connection string. I am getting rid of it and recreating it cause it's a test, I want a fresh database. So I know what I'm working with. Oh, there's all kinds of stuff going on here. I create a new Samurai and then I'm, you know, I'm not going to focus on what it is I'm testing. The bottom line of what I'm doing is I'm creating a new Samurai. I'm inserting it to the database and then I'm checking to make sure that I know that the database is going to be assigning an ID. So I'm checking to make sure that whatever is the ID of the Samurai after I've done the insert is not whatever it was beforehand, right? That I'm really good that the database really stepped in there and did something on the way. So that's what that test is doing and it's starting out doing it against SQL Server. I have another test. Now on this test, I am not, oh, on this test I'm not hitting the database. I'm still doing, you know, creating a new Samurai. I'm inserting it and I'm saving changes but this time I'm just using the in-memory provider. Now, see that I'm passing in in-memory options. I just define them up above just to be that, that's a little cleaner, that's just defined in the constructor. So I'm just passing them in. I didn't use them before though, I used the other. So that's going to use the in-memory and I'm doing what I did before. I'm doing it on one instance of the context and then doing it again on the other instance of the context. So I'm basically kind of proving that I can save stuff. Like however I set up my DB context that just basic functionality being able to save stuff and being able to do a query is working. So my DB context is set up correctly. That's not really testing my business logic even but I need to know that I set up DB, I set up EF correctly. Now I also have a little repository in here and it's not like a repository pattern classic. It's just, I just am calling it that. It's just a class that has methods in it that are the methods I know I need. That's called the connected data class. It has a method for creating a new samurai. It has a method for bringing back all the samurais that are being, that EF is aware of. Queering and loading a graph, calling save changes. And then I also have all this logic for battle. So this is actually something I pulled out of my EF core course. So building all that up and I talk about all that. So what I'm doing is, I want to test something against here, right? So I'm testing, I believe my test is testing a combination of create new samurai and save changes, which is down here. So I want to make sure that my connected data methods are working. Not so much focused on, are they interacting with the database? I just want to make sure this logic is all doing what it's supposed to be doing. So I really don't care about the database. So this is a really good reason to be using in memory. So that's what I'm doing here. I'm creating a context within memory options, right? I'm building the samurai, creating that little, that repository, that connected data class and passing the context in, that uses the in memory options, calling its two methods, create new samurai and save changes, getting rid of the context, instantiating the context again and making sure that I have the samurais. So I'm going to run this three different times. Four reasons for someone to build it. Oh, there they are, okay. So I'm just going to run all of them. All right, can insert samurai into database. That's the one that, that's running. That's the one that's interacting with SQL Server. It's deleting SQL Server. It's recreating the database. It's taking a long time. It's dinner time. Oh, we forgot happy hour. Oh, shoot, 22 seconds. So two things here that I don't like. A, that one took 22 seconds. B, one of my tests failed. Now let me show you, this test that failed can insert samurai via repo. Let me just run it all by itself. Passes. The reason it didn't pass before was because in memory is retaining the objects for the lifetime of the application. So it actually, this can insert samurai with save changes and can insert samurai via repo ended up using the same instance of in memory. So when I got to can insert samurai via repo, there was already one in there. This one was already in there. Then I added this new one and I said the count should be one, but the count was two. Okay. All right, so this is important, right? This is the kind of thing like, I was like, why is this, why is this? So what you need to do is, you might want these all to kind of chain together and have dependencies. In that case, you should also control the order of them. There's a way to do ordered tests, right? But I really want them to be independent. I want this one to have a fresh in memory context and the other one. So what I'm doing back up in my constructor, remember I said I was creating the in memory options. The other thing I'm doing is I'm using the AF cores DB context database and sure deleted method to make sure that. Now this is interesting too. This is one of those things like people who do a lot of testing would know this and this I still don't understand this. Even though it's like the same instance, this constructor is getting hit each time. Like I don't understand that, but the constructor is getting hit each time it's running a new test method. So by deleting that in memory database in the constructor, it's gonna be fresh for each one of the methods. So each one has essentially its own instance of the in memory database? Yeah, because I'm not creating a new instance of the in memory database here, all I'm doing is creating a new instance of the context. So that other code is forcing the in memory database to get deleted. Okay, so ensure deleted creates a brand new copy of the database? No, it just deletes it. All right, and then this will create it for me. It'll go, oh I need that. The other thing I'm doing, remember I said I hated that, how long this thing took? So in my tests, I actually have two things, a few providers installed. I also have the SQLite provider installed. So I just wanted you to see how easy it is to, you know, for a test this makes, unless you're testing, unless you're doing something that really depends on the behavior of a particular database, I can, in most cases, just as easily use SQLite for those tests instead. Right, so now I've fixed those problems, I'll run all the tests again, and so the one in the database was less than a second, but the ones that used in memory are even faster. That's pretty cool. So that's a pretty cool trick right in it, and of its own there to use SQLite. Well it shouldn't be a trick. It shouldn't be, right, right, but it is. It's like, you know, we... Create a SQLite database that has similar structure and could contain just test data. Wait, I don't have to, yeah, because I do, one thing I... Because on the SQLite database is persisted. Yes. So if you want persistence, but you don't want to take a long time, then is SQLite a good option? Yeah, the other thing to take into consideration, my model was so simple that the migrations are, you know, they're okay. Like I don't have a problem with the differences between them. So that is something you need to consider. If you're switching from one database to another, you probably need to create a new set of migrations for that provider and run those if you're gonna use those. Still, you're gonna say 20 seconds per test if it's be worth it. Oh yeah, so this is not an uncommon trick actually to say, you know, I wanna do unit testing, but the database is in the way, but I don't wanna, you know, and maybe, and the in-memory provider isn't gonna solve every problem. Or you're offline. You don't have access to the database. Right, both the in-memory provider, I mean, is still there. But using something like SQLite is something that people have been doing with testing, instead of faking, instead of mocking, they've been just, they're like, well, let's just use SQLite or SQLite and just do it that way, test it that way. Anyway, so those are the kinds of problems though I ran into, not so much the, you know, the database taking a long time, but not really comprehending about that in-memory database kind of sticking around longer. You know, I thought I was gonna create a new one. Right, and it wasn't. So I thought that was an important pattern to show. So, and all of that in Visual Studio 2017. Oh, oh, can I show you one more thing? Of course. Oh, thank you, such a good guy. So patient with your nerdy friends. So I haven't done it. Everything I've done so far has been in full.NET framework. So I do have a project here, which is using.NET Core. And this is the one where I, you can tell because I can edit the CS project. That's how you, right now, that's how you can tell it's a.NET Core project. Okay, so this one's using SQL Server and everything. And I wanted to, there's a couple of things I wanna point out. In Visual Studio 2017, if you're using Entity Framework, EF Core, in a.NET Core project, you have the option, and you wanna do migrations, you have the option of doing migrations through PowerShell, the way we've always done them, add-migration, right, and update-database, or you can use the command line tools. Either way, that's if you're using.NET Core. If you're using just plain.NET, you have to use PowerShell because that's what it's, it doesn't know anything about.NET Core. But I do have the option. But what the team did was the CLI commands look different, right? Because the way the.NET commands are, .NET something, right, at the command line, are different than the PowerShell commands. When you run them, then they point to the same, oh, you can't see that back there. Here are the commands, here are the API that actually does the migration. So when you run them in commands, whether you use the PowerShell words or the .NET, or the .NET words, they call the same APIs, right, it's the same thing. But what the team did was along the lines that have really defined .NET Core and EF Core being lightweight and not putting everything in your packages, everything in your assembly just in case you need it. They split the commands for CLI into a different package that package than the commands for PowerShell. So this, it took me a while to realize it's like actually really an easy way to know. The difference is that the commands are in Microsoft Entity Framework Core tools, tools, plain old tools will give you PowerShell, tools.NET will give you the CLI commands. Okay. So it, because when you see them, you're like, which one's which? How come I can't do this? How come I can't do that? So I can go out to the command line from here. Deep, do you know this? This is one of Mads Christensen's extensions. I have seen that, yeah. Do you know Alessa? I know he does a lot of extensions. Maybe you talk to him a lot. He's got 79 extensions in Visual Studio Gallery. I think we've covered 50 of them on this show. No, it's amazing. This I think, I actually think this one should be built into Visual Studio 2017 because so many people are gonna be using Visual Studio 2017 for working with .NET Core and they're gonna wanna go out to the command line, like me. I could go out to just a regular command line, which is really ugly because of that long prompt. You can't get rid of it in just regular DOS command line. Is it still called DOS? So I'm gonna go out to PowerShell not because it gives me different functionality. What I'm doing in CLI is absolutely no different. I'm going out to PowerShell only so that I can say function prompt open brace that close brace. That's all. That's the only reason I'm using PowerShell for this because the other stuff just gets in the way. So just to prove, I'm sorry it's so dark. You think that's gonna, oh, it looks okay. So I always like to just make sure, okay, .NET's working before I go any further. And it says I've got 1.1. It says that up there at the top. Then clear it again and then .NET EF cross my fingers. That's working. Did you know they put the little unicorn there? Is that the cutest? I think I saw that a while ago, yeah. So notice, so I'm using Entity Framework 1.1. But this again, you're seeing the tools version, right? So the tools version I have here is 1.0.0 MS build three final. It's very specific because the ones, the other ones, the preview ones for Entity Framework. Entity Framework tools packages that say preview are not going to understand the MS build CS Proj stuff. They were focused on, they're built for Project JSON. So I'm using this later. So that name of the tooling. And it's confusing, right? Because it's Entity Framework 1.1, right? This is not Entity Framework. This is just what tools am I using to talk to Entity Framework. And that's the version of the tools. So there's sub commands, database, DB context, and migrations. There's a couple of new ones that have gotten added in .NET, EF, DB context. I like this, this is brand new, info. So this reads the project and finds and tells me the name of the database and the data source. Isn't that cool? That's kind of new. So I'll just clear this again. .NET, wait, thank you. .NET, EF. So I can do migrations from here, migrations. And then after that there's sub commands, one of them is add. And then I can type in the name. I probably already have one. I might already have one in there called init. If I deal it would be like what? Oh no, so it says it's done and you can remove it if you want. So if you haven't seen EF core migrations before, it does the same thing as migrations have always done in response. So it created this migrations folder and it created that init, it created that that. This is really a big deal. This snapshot file is representation of the fact that entity framework core now lets us do migrations in when you're within source control. Because it used to be that this snapshot that describes the model would be stored in your database, right? And if you're working on a team, it was crazy. So now the snapshot is stored in the file, in this file and it's just part of your source control. So that's huge. For people who haven't dealt with that, they're like, why? Who cares? People who have dealt with it will be going fainting on the floor in joy. It was a big, big deal. So you can, there was database, database update, you can script, create scripts, all the same kinds of things that we've been able to do before, but we can, that's part of, I can do this, well not in PowerShell, but I can do this anywhere that .NET Core runs, right? So I've done tons of demos of, which is why I own this pretty little machine. I've done a ton of entity framework core demos in OSX using Visual Studio Code, right? So, and it all just works the same because the EF APIs are the same no matter where I use them. The APIs work in a cross-platform, but they're the same whether I'm using targeting Windows or targeting cross-platform. So, and that's my story. Cool. Stick into it until a new version comes out. Awesome stuff. Thanks. Yeah, oh, thanks. Lots of good stuff. It's good to do. Yeah, we tried to do it a little while ago, but we went and been able to. It was 75 minutes, but it went, it seemed like it was fast. Oh, good, yeah, good. Yeah, and if, you know, we were originally gonna do this in November during the summit, but we wouldn't have had the latest and greatest version of Visual Studio 2017 so thanks. Thanks for coming on. All right, lots of good entity framework stuff there. Hope you enjoyed that and hope you stuck around for all of it. And we'll see you next time on Visual Studio Toolbox.