Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Preview
Start a free Courses trial
to watch this video
Let's review how to use EF to create entities and implement the console application's Repository `AddComicBook` method.
Follow Along
To follow along commiting your changes to this course, you'll need to fork the dotnet-comic-book-gallery-model repo. Then you can clone, commit, and push your changes to your fork like this:
git clone <your-fork>
cd dotnet-comic-book-gallery-model
git checkout tags/v5.2 -b creating-entities
Exercise Solution
Here's the solution to the exercise that's suggested at the end of the video.
foreach (ComicBookArtist artist in comicBook.Artists)
{
if (artist.Artist != null && artist.Artist.Id > 0)
{
context.Entry(artist.Artist).State = EntityState.Unchanged;
}
if (artist.Role != null && artist.Role.Id > 0)
{
context.Entry(artist.Role).State = EntityState.Unchanged;
}
}
As we've seen in an earlier video,
adding an entity to the database
0:00
is as simple as adding it to
it's respective dbset property.
0:04
And, calling the save changes method.
0:07
We can use that knowledge to
implement the add comic book method.
0:10
If you're following along,
see the teacher's notes for
0:14
a link to download the project files.
0:17
The add comic book method is in
the repository class which is located in
0:20
the data folder.
0:24
To start, we need to get an instance
of the context class by calling the get
0:35
context method within a using statement.
0:39
Using (Context context = GetContext()).
0:41
Let's pick the definition for
0:46
the GetContext method
by placing the cursor
0:50
on the method call and pressing alt F12.
0:55
The GetContext method instantiates
an instance of the context class and
1:03
sets its database log property
to an anonymous method
1:08
that writes messages to the output window,
using the Debug.WriteLine method.
1:12
Press the Escape key to close
the peak definition window.
1:19
Now let's finish implementing
the add comic book method.
1:24
First, call the context comic
books DB sets add method,
1:27
passing in the comic book parameter.
1:31
Then call the context save changes method.
1:39
Let's test our changes by setting a break
point just inside of the add comic
1:44
book method, and run in the app.
1:49
Enter A to add a comic book, then Enter
one to select the Bones series four,
1:58
for the issue number,
skip the description for now,
2:04
1/1/2016 for the published on date.
2:09
Skip the average rating, three for
the artist and two for the role.
2:13
Here we are at our break point in In the
Locals window notice that while the series
2:23
ID Foreign Key property value is three,
the series navigation property is null.
2:27
As we discussed in an earlier video
this is one of the advantages
2:33
of defining Foreign Key
properties in our entities.
2:37
We can associate a related entity by
just setting their foreign key property.
2:40
In fact, when adding entities, this is exactly
the approach that we want to use.
2:45
If the series navigation property wasn't
null when adding the comic book entity to
2:50
the context, we'd inadvertently add
a duplicate series record to the database.
2:54
Let's look at an example.
3:00
We're still at our breakpoint.
3:02
I'll press F5 to complete the process
of adding the comic book.
3:04
And enter q to quit the app.
3:07
I'll set the series navigation property
to an instance of the series' entity.
3:16
Comicbook series equals new series
3:21
with an ID of three and a title of bone.
3:26
Now run the app.
3:34
And enter a to add another comicbook.
3:39
Enter 1 to select the bones series,
5 for the issue number,
3:42
2/1/2016 for the published on date,
3:47
3 for the artist in 2 for the row.
3:52
We'll add our break point again.
3:57
Press F5 to continue execution.
3:59
Enter A again to start
adding another comic book.
4:03
Notice that the Bone series
is now listed twice.
4:07
Go ahead and switch back to
Visual Studio and stop the app.
4:12
If we open the sequel server
object Explorer window,
4:18
expand the ComicBookLibraryManager
database, and
4:22
tables and view the data for
the series table,
4:28
we can see that we definitely
have two rows now.
4:34
Why is this happening?
4:38
One of the features of the context
is that it tracks the state of and
4:40
the changes to each entity
that it has currently loaded.
4:44
This is called change tracking.
4:48
When we add an entity to the context
using the DbSet.Add Method,
4:50
the entity is added to the context and
its state is set to added.
4:54
We can verify that by retrieving
the entity's entry in the context
5:01
using the entry method and
checking the value with
5:04
the state property just before
calling the Save Changes method.
5:07
Var comicBookEntry =
context.Entry(comicBook).
5:16
Let's also retrieve the entry for
the series entity.
5:22
Var seriesEntry =
5:28
context.Entry(comicBook.Series).
5:32
Remove the previous break point Set
a new break point on the line of code
5:41
that's calling the Save Changes method and
run the app.
5:45
Enter A to add another comic book,
1 to select the Bone series,
5:55
6 for the issue number 3/1/2016 for
6:02
the published on date,
3 for the artist, and 2 for
6:08
the role, In the Locals window,
6:13
we can see that the comic book entry
state property is set to added.
6:18
That's the expected behavior.
6:22
What might not be expected,
6:25
is that the series entries state
property is also set to added.
6:26
When adding an entity to
the context by calling the D.B.
6:34
said add method, E.F. what not only
set to entity state to added but
6:37
also each of the entities related or
child entities.
6:42
When the Save Changes method is called,
each of the entities in the context that
6:46
has a state of added will be
inserted into the database.
6:50
That's true even for the Bone series
entity that has an ID property value
6:54
which in this case is three that matches
an existing record in the database.
6:59
The Id property value is simply ignored.
7:04
Let's fix this problem.
7:10
After calling the Add method let's check
if the series property isn't null and
7:16
the series entity Id property
value is greater than zero.
7:21
If comic.Book.Series
does not equal null and
7:24
comicBook.Series.Id is greater than zero.
7:29
An Id property value greater than zero
7:36
indicates that the entity
already exists in the database.
7:39
Then let's retrieve the entry for
7:42
the series entity instead
state property to unchanged.
7:44
Context Entry comicBook Series.
7:48
State = EntityState.Unchanged.
7:53
Changing the entry state
from added to unchanged
8:00
will prevent the entity from
being inserted into the database.
8:03
This problem also exists for
the artist collection.
8:08
While we want any of the comic
book artist entities to be added,
8:11
we wouldn't want the related artist or
role entities to be inadvertently added.
8:15
I'll leave adding that code as an exercise
for you to complete on your own.
8:20
If you get stuck,
see the teacher's notes for the solution.
8:24
Let's do some cleanup.
8:29
Go ahead and remove the code that's setting the comic book series property.
8:30
To remove the duplicate series data,
let's delete the database.
8:36
So we'll get a clean baseline copy of our
data the next time that we start our app.
8:40
So, how much defensive
coding is really necessary.
8:49
Well, it depends on the situation.
8:52
If you're the only developer
working on the project,
8:55
then maybe this level of
defensive coding is unnecessary.
8:58
Instead of writing this code, you could
just ensure that you exclusively use
9:01
the foreign key properties and leave
the navigation properties set to null.
9:05
But it's hard to predict how
a project will evolve or
9:10
how your data access layer
might be used in the future.
9:13
Given that, the best option might be
to make your code as flexible and
9:17
reliable as possible.
9:21
You need to sign up for Treehouse in order to download course files.
Sign up