Partager via


Absolute Beginners Guide to Entity Framework

 


The information in this post is out of date.

Visit msdn.com/data/ef for the latest information on current and past releases of EF.


 

To someone who has used emacs or a basic text editor for programming, jumping into Visual Studio 2010 can seem like going from a Cessna to a fighter jet. That’s the experience I had last week starting out at Microsoft, and my goal with this post is to provide others taking the plunge into the Entity Framework – or considering taking the plunge – with a handy guide for what it takes to get up and running. I hope that my fresh perspective will help you in a way that an experienced expert cannot.

The Essentials

The Entity Framework bridges the gap between how developers commonly manipulate conceptual objects (customers, orders, products; posts, tags, members; wall posts, private messages, friend connections) and the way data is actually stored (records in database tables). The technical term for a tool that provides this abstraction is object relational mapper (ORM). ORMs help developers be more efficient and focused, since they don't need to spend brain cycles thinking about how to communicate with the database. It also means that the code is more portable – switching database software requires changing a setting in the ORM, not a rewrite of the whole codebase to match the new database's dialect. As someone who has programmed using the ORM in Django, I can tell you how such a tool makes development less tedious and more enjoyable when you don't have to consider SELECTS and INSERTS. In fact, I've never before written a line of SQL, yet I was able to build a rich web application thanks to an ORM.

Getting Started

One of the nice features of using the Entity Framework is its out-of-the-box simplicity. To my pleasant surprise, I didn't need to download, install, or patch anything to get started with my first EF app. I booted up VS 2010, opened a new project, designed my entities, wrote my code, and off I went. You can probably get a very simple app up and running in about 10 minutes. To prove it, I'll do exactly that as a step-by-step walkthrough below. For this example, I'll make a simple events calendar.

Walkthrough

Begin by opening Visual Studio 2010.

From the 'File' menu select 'New' >> 'Project'. I’ve chosen Visual C# as my language and a Console Application as my format for simplicity. I will accept the default sequential naming that gets filled in for me, "ConsoleApplication2," so you can follow along by matching this with what gets filled in for you, too, though any real application should have an actual descriptive name such as "EventCalendar" or "PayrollProcessor."

 

Visual Studio will now set you up with a basic C# application. You may wish to rename the file from 'Program.cs' to something more meaningful to your project, but once again I'll stick with the default names so you can sync up and provide your own in its place.

 

The next step is adding your entities to the project. To do this, we’ll need to add a new file to our project which will contain the specifications for our entities. Open up the Solution Explorer panel. (If it’s not already in your workspace, you can bring it up by 'View' >> 'Solution Explorer'.) Right-click on the name of your application, in my case “ConsoleApplication2,” and click on the option 'Add' >> 'New Item'. Then, select 'ADO.NET Entity Data Model'. A good naming convention for your data model is to append the word "Model" to the end of your database name or application name, such as "EventCalendarModel" or "HumanResourcesModel."

 

If there was already a database in place that you had to use, then you would select the 'Generate from database' option, and the Entity Framework would do its best to create models and associations that fit the data. If you are starting an application from scratch and get to design the database, as I’ll be demonstrating in this walkthrough, select 'Empty model.' This is known as the model-first approach, instead of the database-first approach.

 

This will now open a new file – a canvas onto which you can design your data model. Rather than having to directly write the underlying XML file to specify the models and properties, this designer is a pretty slick way to configure your models and associate them. You start with an empty canvas.

Begin by adding you first entity. To add an entity, right-click on the design surface (the white canvas area) and click 'Add' >> 'Entity' from the context menu. As I mentioned before, I’m going to use an events calendar as my sample. We will have Users and Events as our two entities. Type a name for the entity, and notice how it automatically attempts to pluralize it in the EntitySet field. EntitySets are collections of entities (that map to tables in the database), which allow you to add, delete, or update entities (rows in the database). In other words, you'll be using this often in your code. Although the system usually gets the pluralization right, you can tweak it as you please. You can leave all of the other settings as their defaults to continue, unless you have a special need to customize them.

The new entity you created will now appear on the design surface. You can drag it around the designer as you please.

The next step will be to add properties to that entity. Properties are essentially "instance data" in the lexicon of object-oriented programming or "columns" in database parlance. You can add a property to an entity by right-clicking the entity and selecting 'Add' >> 'Scalar Property'. When you add the property, you can then name it whatever makes sense.

I’ll name the first one “Title” – the title of the Event. When you have one of the properties highlighted – while renaming it – you can simply press the 'Enter' key to keep adding more.

 

Notice how I left out one pretty important "property" – the Event's creator. That's because I plan to keep track of information about each User and which Events he creates, so a User of the calendar will be it's own entity that is associated with Events the User created. This type of property is called a 'navigation property'. As above, I add the User entity by right-clicking the canvas and clicking 'Add' >> 'Entity'.

I’ll now add two properties to it as above: a username and a password.

 

Finally, I'll add an association between the Event and the User to represent which User created an Event. To do this, right click anywhere on the design surface and select 'Add' >> 'Association'.

To configure the association:

1. Select the two “ends” of the association, or the two entities you will be associating, and their multiplicity to match the association you have in mind. In this case, I am setting up a many-to-one association between an Event and its creator; each Event has only one creator, but each User may have created many Events.

2. Since you may have multiple associations between the same two entities, it’s a good practice to be specific about the association name rather than just using the two entity names. I’ll name this “EventCreator” to be specific about what this association represents and avoid collisions or ambiguity.

3. Customize the navigation properties using terms that make sense relative to this relationship. Rather than just ‘User’ and ‘Events,’ I’ll use the terms ‘Creator’ and ‘CreatedEvents.’ These are the property names used by one entity to get to the other. You would use Event.Creator to get the single User who created that event and User.CreatedEvents for a list of events created by a certain User.

Click OK to create the relationship, and you will see this new linkage appear on the design surface. Notice how the multiplicity of the relationship is represented by the number 1 and the *, one and many, respectively. Also see how the new navigation properties have been added to each entity with the names specified.

 

To demonstrate why it makes sense to be specific with names of relationships and navigation properties, I’ll go one step further and allow Users to add Events to their personal calendar. I will keep track of this by a many-to-many relationship, a second association between an Event and a User. Here’s how that will look:

The extra association appears on the design surface, and the new navigation properties have been added to each entity. Notice how being specific with the naming of the navigation properties makes it very easy to understand – and use – the models, especially when there are multiple associations between the same two entities.

Now I will go through each scalar property I added before and verify that it has the right attributes. Right-click on any property of an entity and click the 'Properties' menu button. This will bring up the 'Properties' panel. Since I’ll be using this panel consistently while I make these tweaks, I decided to pin it to the right of my workspace by clicking the pushpin icon.

Although there's a lot to see in the properties panel, the most important parts right now are the 'Nullable' and 'Type' options specific to that property. I leave the other settings to a more advanced guide.

If you are using an ORM because you have limited database experience, then the term 'Nullable' may need some explanation. A property that is nullable is one that can contain a 'null' value. For example, if 'description' for an Event is optional, then it could be nullable (set this property to 'true'). If, however, you want to require that every Event must have a time, that field should not be nullable (false). In some senses, the word "optional" can be used as a loose analog.

The 'Type' property should be fairly familiar to a programmer – it's just the data type. So a time is probably best represented as a DateTime type, and an ID number is best stored as a 32-bit integer. One nice feature of the Entity Framework is how it abstracts the database underneath. Whereas one database may require a String, another may require that it be called a VarChar. When using the EF, this minor annoyance is abstracted by the database provider.

For this simple example, I have chosen to first add all of the names of the properties to each entity and then return to specify the type and nullability. You can also pause at any time while adding entities or properties to entities to do this.

Each property defaults to a string type. In this example, I've gone through and modified only the 'Time' property of the Event to make it a DateTime type. For all of the others, the default to string (or Int32 for keys) was appropriate.

Now my entities are ready, so it's time to ready the database and start writing code. Right click the canvas and select 'Generate Database from Model.'

From here, select the database connection you'd like to use, or select 'New Connection…'. I'll make a new connection in this example. The specifics of getting your database up and running are beyond the scope of this walkthrough. I happen to be borrowing a colleague's server. One notable feature I will cover is that you can specify a database name in the 'Select or enter a database name' field, and it will create a new database on the server for you if it one with that name does not already exist and you have the proper permissions. Note that clicking 'Test Connection' when you've specified a new database name (one to be created) will fail, since the database doesn't exist yet. Simply press 'OK' to establish the connection and attempt to create the database.

If creating a new database, you should see this dialog box:

Click 'Yes' to try to make the new database on the server. Assuming you've succeeded, you'll return to the original Generate Database Wizard and resume setting it up. The connection string, which tells the EF how to connect to the database, should be filled in for you. Click 'Next' to proceed. Make note of the value in the bottom field, which in my case is Model1Container. This will be needed later in the code to communicate with the database by forming a context.

After it's done thinking, you'll have a DDL file ready to go. Don't get tripped up by the term DDL; all we care about is that this file contains instructions for the database that will get it set up so that you can use your models with it.

This file contains the script that is appropriate for your database to set it up. Click 'Finish' to save that file. It will subsequently open up in VS, and may indicate that it is not connected to the database yet. The next step is to make that connection and run the script. Right-click inside the document and select 'Execute SQL'. Since I'm using SQL Server 2008, the window below pops up and I follow the steps to run the script. Depending on your database, what you have to do to execute that script may vary.

 

After the operation is complete, you'll get a confirmation that it was successful.

 

At this point, the database is all ready to go, and it's time to start interacting with it via code. Here’s a code snippet you can run if you were following along.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ConsoleApplication2

{

    class Program

    {

        static void Main(string[] args)

        {

            /* In order to communicate with the database using the EF,

             * set up a context as in the line below. Notice how 'Model1Container'

             * follows through to here from where I mentioned it above. In order

             * to interact with data from the database in any way, you must establish

             * a context. */

            using (Model1Container context = new Model1Container())

            {

               

                /* One way to create a new entity is to give it all of its

                 * values right away as below. Use the entity names from

                 * your model, and assign the properties that you can. */

                User mike = new User

                {

          Username = "mike",

                    Password = "123456"

                };

                Console.WriteLine("Users before add: " + context.Users.Count()); // 0

                /* Notice how the new user does not get added to the database or the context yet */

                context.Users.AddObject(mike);

                Console.WriteLine("Users before save: " + context.Users.Count()); // 0

                /* At this point, the context knows about 'mike', but it hasn't yet

                 * saved 'mike' to the database. */

                context.SaveChanges();

                Console.WriteLine("Users after save: " + context.Users.Count()); // 1

                /* Now 'mike' has been saved to the database. Any changes to 'mike' from

                 * this point forward will not be saved until context.SaveChanges() is

                 * called again. */

                /* Here's an alternate approach to adding a new entity.

                 * You can continue assembling the entity at various parts of the code.

                 * Warning: Don't try to save an entity if one of its properties has not

                 * yet been set and that property is not nullable. */

                User matt = new User();

                matt.Username = "matt";

                /* If you tried to save here, before setting 'Password', you'd get an error,

                 * since Password is not a nullable field. */

                matt.Password = "654321";

                context.Users.AddObject(matt);

                context.SaveChanges();

                /* Now it's possible to add an associated entity */

                Event bbq = new Event

                {

                    Title = "Barbeque",

                    Description = "BBQ at the office",

                    Time = new DateTime(2010, 07, 04, 18, 0, 0),

                    Location = "1 Microsoft Way, Redmond",

                    /* The simplicity in the following line is EF magic at work;

                     * setting up an association is effortless, despite the extra

                     * work done in the database for such a relationship */

                    Creator = mike

                };

                context.Events.AddObject(bbq);

                context.SaveChanges();

                /* Here, too, a many-to-many relationship becomes simple to establish

                 * despite the extra work being done in the database to organize this */

                matt.ConfirmedEvents.Add(bbq);

                context.SaveChanges();

                /* Now we've got some meaningful data in the database to start querying */

                /* One way to find something you’re looking for is by forming a query as follows.

                 * The "FirstOrDefault" should be used when you expect there to be only one entity

                 * with the properties you specify. */

                User findMatt = context.Users.FirstOrDefault(user => user.Username == "matt");

                Console.WriteLine("Found user: " + findMatt.Username);

                /* Let's see how we can follow a navigation property. Since ConfirmedEvents

                 * is a navigation property for a many-to-many relationship, it will be

                 * something over which we can iterate in a foreach */

                Console.WriteLine("Matt is attending " + findMatt.ConfirmedEvents.Count() + " events, including: ");

                foreach (Event mattsEvents in findMatt.ConfirmedEvents)

                {

                    Console.WriteLine(mattsEvents.Title);

                }

                /* We can also explore the many-to-many relationship in the other direction. */

                Console.WriteLine("Attendees of the bbq:");

                foreach (User attendee in bbq.Attendees)

                {

                    Console.WriteLine(attendee.Username);

                }

                /* Pause at the end of execution */

                Console.Read();

            }

        }

    }

}

/* Output:

Users before add: 0

Users before save: 0

Users after save: 1

Found user: matt

Matt is attending 1 events, including:

Barbeque

Attendees of the bbq:

matt

*/

The code above belies the complexity of what is actually happening behind the scenes. This simplicity is what makes using the Entity Framework so powerful; it makes the developer’s job a lot easier. Beyond what I’ve been able to show in this brief walkthrough, there’s still plenty more to learn about the rest of the Entity Framework before you can fully realize its full potential. Here are some additional resources for going deeper:

Background on Entity Framework: https://channel9.msdn.com/posts/egibson/MSDN-Simulcast-All-DataAll-Day-Dive-into-NET-Data-Access-Deeper-Look-at-ADONET-Entity-Framework/

Great video tutorials: https://msdn.microsoft.com/en-us/data/videos.aspx

Quickstart Documentation: https://msdn.microsoft.com/en-us/library/bb399182.aspx

Helpful Glossary of Terms: https://msdn.microsoft.com/en-us/library/bb387161.aspx

Hub for all things EF: https://msdn.microsoft.com/en-us/library/bb399572.aspx

-Michael Yaroshefsky
Program Manager
Microsoft

Comments

  • Anonymous
    July 19, 2010
    Awesome!  Great job! More like this!

  • Anonymous
    July 19, 2010
    Would like to see a post on how to use this (best practice) in a disconnected scenario.

  • Anonymous
    July 20, 2010
    Michael, Nice post, clear & easy to read. It's well worth in reading. Thx 4 the info.

  • Anonymous
    July 20, 2010
    Great Article! It would be very valuable to have the best practices using EF, VS Database Edition, VSTS and how multiple developers could collaborate, each one updating a part of the schema. We have today a schema comparer in VS Database Edition to maintain the coherency of the database schema and we are facing some synch. problems when updating the Data Model from the Database. This article shows how to generate the database from the model, so the question is: what is the right way to make a team of developers to collaborate in an Agile approach to the construction of the data model? Is it: Create your model in EF first, generate the database, check-in everything in TFS and make subsequent update from the Model-> All developers should then refresh their database schema from the Data Model checked-in in TFS? Or use VS Database Edition, update your schema from the database in which you add/modify tables, and then update the Data Model in EF from your Database? Hope to see content on this topic: Agile Developement of Data Models with VSTS

  • Anonymous
    July 20, 2010
    Very good! How to log the database queries? This is very important since the developers (probably) uses the Sql Server Expression version.

  • Anonymous
    July 21, 2010
    Very nice. An easy way to get started. Thank you.

  • Anonymous
    July 22, 2010
    It's important to note that it's still important to know SQL so you understand what is happening behind-the-scenes. If you don't, just as in LINQ-to-SQL, you could really mess up your app with unoptimized code. It's so hard to make things like this easy for a beginner yet introduce them to important concepts like concurrency and optimized queries.

  • Anonymous
    July 25, 2010
    Best Entity Framework Guide for Beginners

  • Anonymous
    July 29, 2010
    Very well done. Thank you so much.

  • Anonymous
    August 06, 2010
    Hi Michael, Coming from basic text editor person myself, I was pretty dismayed to find the generated code in the edmx a little overwhelming, especially when it came to figuring out what has gone wrong with mappings. I'd appreciate it if in future posts, you could point to some references about what the various mapping layers meant, and how to exercise it. So far, I could only work with straightforward Entity to DB mappings. The rest of the layers are difficult and inaccessible. Chui

  • Anonymous
    August 16, 2010
    The comment has been removed

  • Anonymous
    August 17, 2010
    @Frédéric and @Chui, I have an add-on tool for VS that may help out in the situations you describe. It is a tool that compares the EF model layers (SSDL/CSDL) and shows differences between the layers, and differences between the database and model. It can sync a selection of (or all) differences across the layers and can generate incremental SQL-DDL to keep databases in sync. See my blog for more info: huagati.blogspot.com/.../using-model-comparer-to-generate.html

  • Anonymous
    August 22, 2010
    Followed the instructions above and it works (it makes me understand entity framework). Thanks :)

  • Anonymous
    September 09, 2010
    Would be great if this worked with Sql Server Compact as well. "Could not find the appropriate DbProviderManifest to generate the SSDL. The supplied provider invariant name 'System.Data.SqlServerCe.3.5' is not valid."

  • Anonymous
    September 28, 2010
    This is a terrible piece of writing. You start off by comparing emacs to Visual Studio. I really don't see what this has anything to do with the rest of the article or Entity Framework. The whole premise of "ORMs help developers be more efficient and focused, since they don't need to spend brain cycles thinking about how to communicate with the database." is fundamentally flawed and incorrect. If you make an app you have to think about scalability and performance. In order to be aware of those issues you need to know about the SQL queries that are generated via EF and the underlying architecture. If you ignore that aspect then you'll have a serious problem sometime further in the development cycle. I'm sorry, but naming your project "ConsoleApplication2" is sloppy and amateurish. You could at least give your project proper sounding names. Aside from that yes, this document will get you up and running but it's a shoddy piece of writing.

  • Anonymous
    October 06, 2010
    Thanks for this post. It helped me get my first EF app up and running in minutes.

  • Anonymous
    October 19, 2010
    The comment has been removed

  • Anonymous
    November 04, 2010
    I have Visual Studio 2008 Sp1 and SQL Server Express 2008 R2, when I try to create the database from the entiries I get an error for ann entities and associations I created saying: Error 11007: Entity type 'Event' is not mapped. The EventsSampe db is not in the ManagementStudio but it shows up in Visual Studio. What can I do to correct it?

  • Anonymous
    November 23, 2010
    Yea this is good. However I get an exception. UpdateException was unhandled. An error occurred while updating the entries. See the inner exception for details. at the first context.SaveChanges();

  • Anonymous
    November 27, 2010
    Wonderful article. thanks so much. but i have a little problem. i add an event to the userse confrimed events like: ugur.ConfirmedEvents.Add(mangal); context.SaveChanges(); but when i query the count of confirmed events i get zero. User bulUgur = context.UserSet.FirstOrDefault(user => user.UserName == "ugur"); Console.WriteLine("Found User : " + bulUgur.UserName); Console.WriteLine("Ugur have " + bulUgur.ConfirmedEvents.Count() + " evets"); Result : Found User : Ugur Ugur have 0 events.

  • Anonymous
    January 07, 2011
    The comment has been removed

  • Anonymous
    February 16, 2011
    The comment has been removed

  • Anonymous
    February 16, 2011
    Nice introduction. I notice you've tried to blank out your username from the screen-shots, but you've missed one: the "Generate Database Wizard : Summary and Settings / DDL" screen.

  • Anonymous
    February 16, 2011
    Thanks a million.. .I just wish people like you would write these guides. there is a lot of information in MS site but, event the lenguage they use is extrange to us using guides to learn. MS should open a novice learning site/forum  where they follow your steps of teaching...    1.Assuiming we know nothing no XM?#$/*Cs achronyms.     2. of course the screen shots helped a lot.    3. Possible errors which we doand what to do.    in other words get a novice and see if they learn in one shot, using the guides they write. since you are a program mgr. .. you have experience in giving info.... i see a lot of the gurus teaching step by step from level 1 up...which is wrong. they dont' notice but their language is way too advanced and they go too fast... (gurus to their guru site.) I beleive there is a way to know how good teaching is, when you see people on internet trying to find answers to simple questions... MS might not be providing good starts for any technology as RIA services. or others Thanks for putting your time to teach us. ( have to post again...sorry if dup)

  • Anonymous
    March 06, 2011
    Great introduction to EF! One remark, though: "The "FirstOrDefault" should be used when you expect there to be only one entity with the properties you specify" => If you expect there to be only one result, you should use SingleOrDefault, not FirstOrDefault.

  • Anonymous
    March 08, 2011
    Thanks for writing this, it gave a nice simple intro to what EF looks like, which can be hard to find.   One thing I'd mention, and it could be that I'm just using a different version, but I didn't have an AddObject on my users collection.  Instead, I call to call "context.AddToUsers".  Took a little googling to get past that, but otherwrites great article.

  • Anonymous
    March 15, 2011
    This is very helpful.  Thank you!

  • Anonymous
    April 26, 2011
    Great article! Appreciate the effort and detail that went into it! I recommend this post in my own blog: http://vbktech.wordpress.com/

  • Anonymous
    August 27, 2012
    nice article,really good to understand bigeners .thank u

  • Anonymous
    March 26, 2013
    Perfect tutorial, precisely what I needed!

  • Anonymous
    March 28, 2013
    Merci Michael :)

  • Anonymous
    May 13, 2013
    Excellent blog for a starter like me... Thank you Michael!!!

  • Anonymous
    October 02, 2014
    Thanks for the article, and for the notification that it is out of date. I nevertheless got a log out of it. Perfect writing! Thanks very much Rob

  • Anonymous
    October 23, 2014
    I have Visual studio 2013 version, in MVC4 i want to connect to SQL sever but i could not able to connect. Kindly help.

  • Anonymous
    October 24, 2014
    @Kiran - You can find the current getting started docs for EF here - msdn.microsoft.com/.../ee712907. If you need additional help, then start up a question on StackOverflow.com with the entity-framework tag.

  • Anonymous
    January 30, 2015
    Spent a long time searching for a good intro. Glad I came across yours. Excellent!!!