Introduction to Entity Framework: Part III - Building the Model

This is part three of my tutorial series on Entity Framework. If you have not read parts one or two and do not have a good understanding of what an Object Relational Mapper (ORM) is or how to setup a basic SQL Server Express database, then please read those parts first.

Table of Contents


Building the Model

Once you have your database setup and your relationships defined, setting up your model is a breeze. Let's go ahead and start building our model. Just follow these steps to create your Entity Framework model.

  1. Right-click your project node and go to "Add" > "New Item".

  2. From the list, choose "ADO.NET Entity Data Model". Name it "MyEntities.edmx" and click OK.

  3. Next you'll see a screen asking you if you want to create an empty model or generate one from a database. Hopefully it's obvious to you that we want to create one from a database.

  4. From the next screen you should see a drop down menu asking which data connection you should use to connect to the database. Expand the list and you should see the sample database we created in part two. Select it and check the box that says "Yes, include the sensitive data in the connection string" if it lets you. Then ensure that "Save entity connection settings in App.Config as" is checked. Leave the name the default. Click next.

  5. On the next screen you should see three nodes. The first node should be "Tables" and should have an arrow to the left that you can expand. If you expand it you will see the tables we created. Check the box next to tables and click finish. You should see the EF design surface display with a visualization of your database as a model.

    Notice that it even has a visual representation of the relationships you defined in the database relationships wizard.

What Just Happened?

The model you just created is much more than just a simple diagram to represent the underlying database in a visual format. You generated an XML file that represents your database tables as entities, but what you may not realize is that you also generated a C# file called MyEntities.Designer.cs. This C# file is where your entities were created as C# objects. I will show you how to take advantage of this shortly, but it's important that you realize what you actually did just now. You actually generated C# code. All the work of creating C# objects that represent data from your database is gone. Entity Framework created those objects for you and now all you have to do is use them. This tool just saved you several hours of work.

Now What?

Now we get to the fun part, actually using our entities in our application. To use your newly-generated entities you will need to become familiar with what is called an "entity container" or "data context". An entity container is simply an object created by the entity framework. This object contains collections of entities as properties. Using LINQ you are able to query these collections from within C# itself rather than writing SQL queries. To use your entity container you have to first instantiate it. Go ahead and open up the Program.cs file in your console application and modify the Main() method to look like this:

static void Main(string[] args)  
{
    // Instantiate your entity container.
    MyEntitiesContainer container = new MyEntitiesContainer();

    // Now lets create some sample users.
    User sampleUser1 = new User
    {
        Username="Jakinator",
        Password="IllBeBack"
    };

    User sampleUser2 = new User
    {
        Username="ILoveKittens",
        Password="meow"
    };

    User sampleUser3 = new User
    {
        Username="SoccerMom",
        Password="MyKidsAnHonorStudent"
    };

    // Now add the sample users to the entity container.
    container.Users.AddObject(sampleUser1);
    container.Users.AddObject(sampleUser2);
    container.Users.AddObject(sampleUser3);

    // We've added the users to the data context (entity container) but these changes won't
    // be added to the database until we call the SaveChanges() method on the container.
    container.SaveChanges();
}

In a relatively small amount of code we added three users to the database. Remember how hard that would have been if you did it with plain ADO.NET like we did in part one? The syntax here makes it really easy to see what's going on and severely decreases the amount of code you have to write. Before you run your program let's modify this a little more to add some blogs and post comments.

...
container.Users.AddObject(sampleUser1);  
container.Users.AddObject(sampleUser2);  
container.Users.AddObject(sampleUser3);

container.SaveChanges();

// Create a new blog post.
BlogPost samplePost = new BlogPost  
{
    DatePosted = DateTime.Now,
    Title = "Why Terminator is the best movie ever!",
    Body = @"Terminator is the best movie ever because it's the only one I've ever seen.
        It was so awesome that when I finished watching it I vowed to never watch another movie again."
};

// Create sample comments for the above blog post.
PostComment sampleComment1 = new PostComment  
{
    UserId = sampleUser1.Id,
    DatePosted = DateTime.Now,
    Body = "First! I'm always the first to comment on my own blog posts. I'm just awesome like that."
};

PostComment sampleComment2 = new PostComment  
{
    UserId = sampleUser2.Id,
    DatePosted = DateTime.Now,
    Body = @"Jake I completely disagree that Terminator is the best movie ever for one reason: 
        There were no kittens in Terminator. If there were kittens, then maybe..."
};

PostComment sampleComment3 = new PostComment  
{
    UserId = sampleUser3.Id,
    DatePosted = DateTime.Now,
    Body = @"I would never let my kids watch horrible movies like this. 
        They should be at soccer practice or doing homework. 
        That's why my kids have all straight A's and are all honor students."
};

// Add the sample comments to the blog post's collection of post comments.
samplePost.PostComments.Add(sampleComment1);  
samplePost.PostComments.Add(sampleComment2);  
samplePost.PostComments.Add(sampleComment3);

// Add the blog post to the first sample user's collection of blog posts.
sampleUser1.BlogPosts.Add(samplePost);

// Persist changes to the entity container to the database.
container.SaveChanges();  

This is a lot more code this time around. Hopefully you can see what's going on here. We created three users and added them to the container. We then created a blog post and three comments. Then we added the comments to the blog post and the blog post to the user. There are several things to take note of here. First, notice that we called container.SaveChanges() after we added our sample users. If you notice, we didn't set the Id property on our three user objects. The reason for this is that the Id column in the database has Is Identity set to yes; the database is supposed to create an Id for us. Until our changes are saved to the database our user objects would have no Id set. However, after calling container.SaveChanges() their Id properties get populated with the value the database used for them. This allows us to set the UserId on the post comments later in the code.

Now I bet you're wondering why we didn't set the UserId property on the blog post, or why we didn't set the BlogPostId property on the post comments. We used a neat little feature called navigation properties. If you look back up at the picture of our model you will see at the bottom of your entities that you have some navigation properties. Because EF was able to detect the relationships we set up, it knows that a user can have many blog posts, a blog post can have many comments, and a user can have many comments. It then creates these navigation properties for us. When you add a blog post to sampleUser.BlogPosts you are automatically associating that blog post with that user. If you tried to add the blog post to the collection on the container container.BlogPosts.AddObject(newBlogPost) then you would have to set the UserId property because it would not be able to populate it on its own. The same thing happens with post comments; by adding them to the blog post object the BlogPostId property is automatically set. We do have to set the UserId property though because we aren't adding it to a user object, though we very well could have done that and then set BlogPostId property ourselves.

Go ahead and run your program. Your console should pop up and then close again real fast. In that split second it took to run your application you added three users, a blog post, and three comments to the database. Pretty nifty eh? Let's see now how we get that information back out of the database. This is where LINQ comes in and saves the day.

LINQ to Entities

Even though modeling our database and creating objects (entities) on the fly makes things a lot simpler, we've still only scratched the surface of the power of Entity Framework. So far, we have only used plain entity objects and their collections on the container to create and add some entities. We have not applied the power of LINQ to these collections. Before I get into a detailed explanation of how things work I want to show you a sample query.

Now that we have some data in our database, go ahead and remove all the code you added to the Main() method in your console application. Then modify the method to look like this:

static void Main(string[] args)  
{
    MyEntitiesContainer container = new MyEntitiesContainer();
    User myUser = container.Users.Single(x => x.Username == "ILoveKittens");
    foreach (PostComment postComment in myUser.PostComments)
    {
        Console.WriteLine();
        Console.WriteLine("Comment by: {0}", myUser.Username);
        Console.WriteLine("Date Posted: {0}", postComment.DatePosted);
        Console.WriteLine("Comment: {0}", postComment.Body);
    }
    Console.WriteLine();
    Console.WriteLine("Press <ENTER> to continue.");
    Console.ReadLine();
}

It's super easy to read data in from Entity Framework. Here we created a User called myUser and assigned it a user from the container via a LINQ query. We then looped through that user's post comments and if there were any then display them in the console window. If you followed the steps above to add data to the database then the result of running this should look like this:

Congratulations, you now know how to add data to the database as well as read it back. I will go into some more details about LINQ to Entities in part four of this tutorial, but if you need additional details in regards to LINQ in general then please see my Introduction to LINQ tutorial. Before I end part three I want to show you quick samples of how to update and delete. First delete, because it's super easy.

User myUser = container.Users.Single(x => x.Username == "ILoveKittens");  
container.Users.DeleteObject(myUser);  
container.SaveChanges();  

That's all you have to do to delete an entity. When I first started using EF it was the update part that really confused me. To update an entity all you have to do is change properties on the entity you retrieve from the container and then call container.SaveChanges(). At first I didn't understand why I didn't have to call something like container.Users.UpdateObject(myUser), but then I read about self-tracking entities. Entities you retrieve from the container have code in them that tracks all the changes that are made to them. When you call SaveChanges() on the data context it already knows everything that changed and persists those changes to the database.

User myUser = container.Users.Single(x => x.Username == "ILoveKittens");  
myUser.Username = "IStillLoveKittens";  
container.SaveChanges();  

That's all you have to do to update an entity.

Part IV - IQueryable

Chev

Read more posts by this author.

comments powered by Disqus