Okay, so now we've got our entity in place.
Let's go to our store context.
Next as we're going to update our Dbcontext class.
Now we're going to add another DB set I'll say prop DB sets.
And this one's going to be for the baskets.
And we'll specify baskets inside here.
And once again I'm just going to make this required.
Now we don't need to add a DB set for basket items.
Even though this is going to be a table in our database.
Because we've got the relation inside here from the baskets to the basket item, then Entity Framework
by convention will create the table for this, but it might not create it quite how we want it, because
in the store context we're going to have based on conventions, because we've got a DB set in here called
baskets.
This is going to be the name of the table and also based on convention, how we've laid out the code
in our basket with the navigation property to the items here.
Then this is going to set up the foreign key relationship between the basket and the items.
For a one to many relationship, one basket can have many items.
Also from our basket item because we've got the navigation property in here for the product, then it's
also going to set up the relationship between the basket item and the product.
It may not be exactly how we want it though.
So typically at this point we would create a new migration and see what Entity Framework managed to
configure for us based on conventions.
And then if we need to tweak it, we can remove that migration, come back, make some tweaks and then
create another new migration.
That's the approach I just want to demonstrate now, as when you do create a new migration, you're
not stuck with it.
You can remove it and make tweaks, then create another migration or replace that migration, I should
say, with an updated version, check that one and then go through that same process again if you need
to.
So let's open up the terminal and we'll go to the terminal where we're running our API server.
Now it tells us that we need to restart our API, but I'm actually going to stop it at this point,
as when we do mess around with migrations and database functionality, we do need to stop our API server
because it builds and compiles our code when we use these commands.
So inside the API folder I'm just going to say dotnet f migrations at and say basket entity added.
And we don't need to specify an output directory because we've already got a migration in there.
So it's going to be located in the same folder.
So I'll press return and see what happens.
And that was successful.
So let's go take a look and see what that did give us.
So inside the data migrations folder we've now got a new migration for basket entity added.
And let's take a look at the highlights inside here.
So we're creating a table called baskets.
Perfect.
That's what we want inside here we've got an ID column that's going to be SQLite Autoincrement ID and
we've got our basket ID column which is going to be a string.
And it's not allowed to be nullable.
We have to provide that.
And we've got our primary key which is set to our ID of the basket.
Now in the second one we've got another create table, but it's called basket item.
And that does not make me happy because I like tables in the database.
Even though I barely look at the database I still want them to be pluralized.
No good reason for that, but that is kind of conventional to pluralize table names, so I would like
that to be pluralized.
Now please don't be tempted to do this.
And and the name you want in manually that will work.
That will name the table correctly.
But if you remove a migration and add it back in, you're manually edited, change is not going to persist.
So really you want to create your migrations from your code without making any manual adjustments inside
here.
Even though technically you can get away with it.
And let's see what else we've got inside here as well.
So we've got our basket item, then we've got the basket item ID, the quantity and the product ID.
All good.
But we've got another issue here that doesn't make me happy.
The basket ID could be nullable.
Now is that a problem?
Do we want basket items without a corresponding basket?
Because that's what we have potential to do there.
I'm going to say no.
I want every basket item to be associated with a basket.
And that's going to have a further impact down here as well.
Because what we have is the relationship being set up between our basket item and both the basket and
the products tables.
Now, inside the products relationship between the basket item and the products, we have a delete behavior.
What's going to happen if I delete a product from the products table.
Then that's going to cascade into the basket items and remove that item from any baskets where that
product was being used.
But we do not have a similar action for the basket items.
So that means we could delete a basket, but we would not necessarily delete the basket item.
So again, something I'm not quite happy about there either.
And what we also have is indexes being created as well.
Great.
Okay so we've got a couple of tweaks I would like to make inside here because I'm fussy about the table
names, and I don't like the idea of the potential to have orphaned basket items in our database.
So we have numerous different ways of configuring this, and my preference most of the time is to stick
with conventions where possible and attributes where possible.
But we can come in and also configure our store context.
We could override what's going on in here.
What we could do is if I specified override and press space, then one of the methods inside here is
the on model creating.
And what we could do is configure our entities using this approach.
I'm not going to do that for now.
We'll take a look at that maybe a bit later on if we need to.
And the approach I'm going to take a look at is using conventions.
So for the basket item I don't like the table name just being basket item.
So what we can do here is we can specify table and use a data annotation attribute.
And then we can give the table a name.
And I'm going to call this table basket items.
Doesn't make any difference to how we access this in code, but it will affect how it's displayed in
the database for the table name.
That's one thing I wanted to adjust.
The other thing was to deal with the fact that we've got the potential to have a basket item that's
not associated with the basket.
We don't want that behavior either.
Now, the way we do this in conventions, if we come to our basket item, then we can what's referred
to as fully defined relationship with our entity.
Now in the basket, we've defined the basket item inside here.
And to fully define this relationship we add the equivalent navigation property inside this class as
well.
So as well as the product ID we're going to have a prop that's an int for the basket ID.
And we're also going to have a prop for the basket and call it basket.
And we'll also make this required.
And I didn't get any problems creating the migration with this required.
So that's good.
We don't need to make this nullable or initialize it to null inside.
Here we can use this required modifier.
We never used to be able to do that.
By the way.
That does seem to be something they've fixed I guess in dotnet nine.
And let's go back to our terminal.
And I want to remove this migration.
So we'll use the command dotnet f migrations.
Remove and press return.
By the way, this command will only work if you have not already applied this to your database.
So I've got my API server stopped.
So there's no way that this previous migration or this migration here has been applied to the database.
So I'll press return.
And this should be removed without issues.
Or it would have been.
But I've got a problem and it tells me that required member basket.
Item basket must be set in the object initializer or attribute constructor.
And that's the reason that I did want to not make this required, because we cannot create a new basket
item without also specifying the basket inside here.
So we would need to specify the basket ID at a minimum I think.
Let's just add that in.
No, we would actually need the basket entity in there.
So that was the reason why I was thinking that the required property would not work for this, and indeed
it doesn't.
So what we do in this scenario is we don't supply the required property, but we do give this an initial
value of null, which is not allowed because of the nullable reference type setting we've got.
But we can override it with an exclamation mark.
And that is the solution to lists.
So now I've removed any errors from my code.
I'll go back to the terminal and let's repeat that command to remove the migration.
And that should work without issue.
And sure enough it has.
So let's clear the window and let's repeat the commands to add the migration for basket entity added.
And great.
Now that has been created.
So let's go back to Solution Explorer and open up the migration.
Make sure that the changes we wanted are in place.
So I can see that the table name is called basket items.
I can see that the basket ID is no longer allowed to be nullable.
And what I've also got in here is the referential action cascade for the basket item, which means if
we were to delete the basket, then that also ensures that any related basket items also get deleted.
So great.
Now we just need to make sure our application starts so that we can apply that new migration to our
database.
So I'm just going to execute dotnet watch, press return and make sure our application starts up cleanly.
And indeed it does.
And we can also go take a look at our database file.
And if we click on store db what we should find is that we've now got a baskets table with the ID and
basket ID.
And we've also got the basket items table inside here.
And we can see the foreign key relationships have been set up with that little white key here to say
that these are the foreign key IDs.
Perfect.
So now we have that in place.
What we'll take a look at next is creating a basket controller.