chris-cornish / fitness-frog

C#/.NET Final Project for Code Louisville
0 stars 0 forks source link

Finish DbContext & Entity Configurations #7

Open sclayturner opened 8 years ago

sclayturner commented 8 years ago

Okay @chris-cornish. We're in the next tier. If you follow the Contoso University example, you won't find some of what we're applying here... We are doing a little deeper dive to provide more flexibility in how Entity Framework maintains our SQL Server database, and how it carries out its function as an Object/Relational Mapping (ORM) facility. Entity Framework will do a lot of work for you by default based on it's own, preprogrammed conventions, but that doesn't mean you want it to follow someone else's preprogrammed conventions. We use the Fluent API in this tier to give us more control. It's a "little" more work, but will demonstrate a much more mature understanding of things.

That said, we are using Entity Framework Core, and as with all things ".NET Core," this is all "new" stuff, and not totally defined. I am following what I can find and interpret as the best, current implementation of this new stuff, but it differs a little from how it was done in Entity Framework 6. In other words, we might have to refactor a bit when we get to the point of testing an initial creation of the database from the code we're writing (our first "migration.")

What I want you to do, is follow the pattern you see that I have set. Look at the FitnessFrogDbContext first. Look for my TODOs. Flesh it out. It will not compile until you add the additional EntityConfigs for each model. Follow my pattern there as best you can and ask questions/post code.

sclayturner commented 8 years ago

Subsequently, the product of this exercise will not only tell the ASP.NET app (or any app that references the assembly) how to talk to the SQL database, it will literally "build" the database for you.

chris-cornish commented 8 years ago

Awesome. Haven't done too much with EF yet and Db, so I'll see what I'm able to do.

chris-cornish commented 8 years ago

Treehouse has yet to release their video on EF, but found that code louisville had posted a few videos speaking on it, two of which was just made by one of the mentors.

sclayturner commented 8 years ago

Note that the youtube video contribution is using EntityFramework 6, which is now deprecated and not the go-forward way with EntityFramework Core, which we're using. So.. There will be differences. Also, he is building everything out in one assembly, etc. Don't take what he's saying as gospel, but rather an introduction of some concepts.

Basically, there is not a ton of "new" documentation out there for EF Core. Most of what you're going to find is EF 6 or below.

sclayturner commented 8 years ago

On the LocalDB discussion, it's good to be familiar with, but you won't be doing much with the database except for see what EntityFramework creates there for you automagically once we complete that tier and run our initial migration. The idea with code-first is that you don't really have to do much with the database itself besides assume that it's there to connect to.

chris-cornish commented 8 years ago

Oh okay. I'll look more into EF Core than.

sclayturner commented 8 years ago

@chris-cornish You need to rework this... You've added multiple constructors and multiple initializers to the same UserEntityConfig class. What you really need to do is create separate files, each having its own configuration... ExerciseEntityConfig.cs, FoodEntityConfig.cs, etc. Each will have its own constructor and initializer. The initializer will set all the options we want for the specific class we're talking about.

sclayturner commented 8 years ago

Exercise.cs will have a corresponding ExerciseEntityConfig.cs in the Domain.Data assembly, Food.cs will have a corresponding FoodEntityConfig.cs in the Domain.Data assembly and so on. In the FitnessFrogDbContext file, the first section is fine (listing DbSets). But, the OnModelCreating method needs to look like this:

        new UserEntityConfig(modelBuilder.Entity<User>());
        new DayEntityConfig(modelBuilder.Entity<Day>());
        new ExerciseEntityConfig(modelBuilder.Entity<Exercise>());
        new FoodEntityConfig(modelBuilder.Entity<Food>());
        new NoteEntityConfig(modelBuilder.Entity<Note>());
chris-cornish commented 8 years ago

Not sure why I didn't catch on to that the first time around. Makes a lot more sense now. For now as I'm working on this Issue, i'm going to commit it all on a new branch (FitnessFrog-v7 [v7 for version relating to issue 7]) until finished and you sign off on it.

sclayturner commented 8 years ago

Fair enough.

sclayturner commented 8 years ago

@chris-cornish When you are finished with your changes, go ahead and create a Pull request for this branch so I can review and merge into the master to update my own local copy.

chris-cornish commented 8 years ago

@sclayturner Alright I think I'm all done with that branch and created a pull request.

sclayturner commented 8 years ago

@chris-cornish I made some updates and committed them to the master. You can look at the changes by clicking on the latest commit number 1e2604d. For your part, you did fine. There were a couple of copy/paste issues with needing to rename keys in configs, but that was about it, and everyone does that until they fail to see the behavior they want - then they fix it. I also added a few more config options to properties on the EntityConfig files just so the database creation sets the right constraints for us when we run that first migration that creates the db.

So, I also added "User" as a "navigation property" on all models that carry the UserId property so that we'll have access to all of its loaded members as opposed to just the UserId integer itself. In other words, if we have UserId 555 and 555 is John Smith, then we will now automagically have all of John Smiths user information available to us off the model. Example: Console.WriteLine(myDay.User.Name); Result: "John Smith"

In the models, I grouped the properties together, separating the properties that actually get assigned values in the database from those that are just derived because they are related with a foreign key, i.e. the ICollections and the User "navigation" properties. This way, when you compare the properties in the model to the properties that get configured in the corresponding EntityConfig file, it's just easier to make sure you got them all if they're in the same order... Readability is key, both for you and anyone else inheriting your code.

I removed the Notes collection from both the Food and the Exercise models. It was just a little too convoluted to reference notes from those models, and EntityFrameworkCore does not seem to be mature enough yet to scope it that way. Instead, Notes will be assigned to the User him/herself (User -> Has -> Notes). In other words, the user will have a log of notes that are date/time stamped and easily sorted as such. We can also still tag a Note as having originated from a given Food or Exercise by keeping the NoteType and NoteTypeId. You'll see how that gets applied when we work with the Controllers in the UI project...

The next step is for me to test having it create the first migration that would create the database and make sure everything we've specified in code actually translates correctly given the fact that some of this is new and raw with Core. I've had to make some educated guesses and I'll know if they're right soon. We'll then schedule a session together so you can see it create the database on your machine and finally understand exactly what all this actually does for you in a concrete way. Then we can advance the project forward next week.

In the meantime, review what I've pushed. Ask any questions if you're not sure what we're doing and why on anything so far, BUT... I'd recommend spending your next chunk of time diving into the ember-sandbox in the globally-linked repository.

chris-cornish commented 8 years ago

Pulled it down and looking over it all now. Going to have to research more on primary/foreign keys, still pretty new to me and need to get a better understanding. Also take more time to really see how the different aspects of the project are relating to one another. Have noticed when looking things up, the way things are defined are still rather confusing as the vocabulary is all rather new still, so it's taking longer to grasp what things are doing until I've used them over and over (it's tough being a visual learner).

@sclayturner One thing I was wondering is whether or not EF 7 was the same thing as EF Core? I see it says that EF7 is now Core, but didn't know if 7 was an older version or was just renamed to Core.

Earlier today I had tried to 'fetch' the updated globally-linked repo, but had some issues since my local repo was different and the merging wasn't as friendly to me a VisualStudios is. Ended up deleting local and cloning it fresh.

Last thing, is it still alright if I use your PluralSight account? Had forgotten about it until looking up EF Core and PluralSight came up as a result and had a course on it. Wanted to see what other courses they had as well that I could look at. TreeHouse right now has an Ember course I've bookmarked and will take, but nothing on any EntityFrameworks right now.

As always I can't thank you enough for all the help and time you devote.

sclayturner commented 8 years ago

On primary/foreign keys (entity relationships) knowledge, that's perfectly fine. Most ORM implementations assume some minor database experience. Basically, you just need to get a good overview of the difference between a one-to-one relationship and a one-to-many relationship. In our example project, one User has many Notes. A User has many Days. When we say "primary key," we're always referring to the Id of a single instance of an object. That primary key may appear on other entities as a "foreign key." In other words, UserId is the primary key for a user, but appears as a foreign key in Notes in order to denote that the specified User created and owns the Note. It's actually simpler to see and understand "I think" looking at database explanations. How these relationships get defined "in code," is a little more confusing in my opinion. Remember, defining these relationships and enforcing them in an ORM was an afterthought that came many years later...

About 18 months ago, Microsoft made a MAJOR strategy shift. The CEO announced that the .NET Framework and all coding tools including VisualStudio would become "open source" and "platform independent." This was huge and came as a surprise to some. Not to me. They had to do it. All these open source platforms they now pattern themselves after were eating their lunch. It was a surprise to the teams working on an Entity Framework 7 release and the .NET Framework 5.x. Suddenly, what they did and why changed. So... They also changed the name also. If you see .NET Framework 5.x, that is really .NET Core 1.x. If you see Entity Framework (EF) 7. That is really Entity Framework Core 1.x.

With the ember sandbox project, think about some of the things we've said the app will need to do and just play around (a) with the basic syntax and convention - getting it to do "anything" really, and (b) the log-in process using LinkedIn, Google, or Facebook as the authentication service. There should be tons of examples.

My Plural account username is clay@onovative.com. I'll text you the password later.

chris-cornish commented 8 years ago

Perfect, thanks. I'll get started on messing around with ember sandbox.

sclayturner commented 8 years ago

Good deal. And just keep this in mind... I am showing you a more "mature" way to implement EF. A lot of the videos and walkthroughs you see will throw everything into one assembly AND rely on EF's default conventions for configuration.

Our Domain assembly is where we build the models, and those models structurally "map" directly to database tables, pretty much exactly. Having a separate assembly allows us to write these models one time, and use them in any application; not just the ASP.NET app we're demo'ing.

Our Domain.Data assembly is really what "informs" EntityFramework about "how" we want models to "map" to database tables. We've added the EntityConfigs in order to "super" control how it "maps" models to db tables, but you could completely not have these and EntityFramework would talk to the database and map things fine... "Fine," however, is a relative term here... If I "didn't know any better" as a developer, then I wouldn't know or care to add these EntityConfigs or have the flexibility to change how EF manages the db... But... Because I (and other senior project leads) "do know better," having written and optimized databases for performance "apart from EF," "fine" is defined as "the thing better perform well" and I don't trust EF default conventions to tune the database or interactions with it to par. A senior person is going to want to have the flexibility because the database is critical as the foundation for performance... If you demonstrate having done considered this at the onset, then you, my friend, separate yourself from the thousands of other newbie software developers who just go Contoso U...