AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=2067&pId=-1
Code First Development Using the Entity Framework
page
by Vince Varallo
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 20773/ 33

Introduction

When the Entity Framework was first introduced developers could generate a model from an existing database.  This is called Database First development.  Then the next round of enhancements to the Entity Framework allowed the developer to create the model and then generate a database from the model.  This is called Model First development.  With the release of Entity Framework 4.1 developers can now develop their classes with all the properties and then generate a database from the classes.  This is called Code First Development.

Code first works great if you are the type of developer that thinks about the object model or business logic layer first.  You can build all your classes and test out functionality before building the data model.  You could consider using this type of approach at the beginning of a project when changes are happening rapidly and you want to get up and running with a prototype quickly.

This article will demonstrate how to use the new Code First features in Entity Framework 4.1 to create a database.  You must install Entity Framework 4.1 for these features to work.  You can download the setup file here.  The code for the sample can be found here.

The sample will create an Invoice class and a LineItem class.  From these two classes a database called Accounting will be generated with two corresponding tables.  The you'll be able to bind the records in the table to a GridView control and also Add, Update, and Delete the records in the database.  Finally, the sample will show you how to modify a database if the classes change.

Code First Development

Step 1: Define the "Entity" Classes

1.   Launch Visual Studio 2010.

2.   From the Start page click on the "New Project…" link.

3.   Select ASP.NET Web Application from the list of C# templates.

4.   Name the project EF4CodeFirst and click the OK button.  Visual Studio will create a web application with numerous default files.

5.   Right click on the project in the Solution Explorer and select AddàClass… from the pop-up menu.

6.   Name the class Invoice.cs and click the Add button.  The Invoice class will be used to generate a table called Invoices in the database.

7.   Add the following properties to the Invoice class.

public class Invoice
{
    public int ID { get; set; }
    public DateTime InvoiceDate { get; set; }
    public double Total { get; set; }
}

The first property is called ID.  The entity framework is smart enough to realize that if you have a property called ID or ClassNameID that it will create that field as the primary key and make it an identity field.

An invoice has must have one or more line items so we'll create another class called LineItem to represent this entity and then create a LineItems property in the Invoice class to represent this relationship.  The entity framework will recognize this relationship and create a primary key\foreign key relationship in the database automatically.

8.   Right click on the project file and select AddàClass… from the pop-up menu.

9.   Name the class LineItem.cs and click the Add button.

10. Add the following properties to the LineItem class.

public class LineItem
{
    public int ID { get; set; }
    public string ProductName { get; set; }
    public double ItemCost { get; set; }
    public double Units { get; set; }
 
    public Invoice Invoice { get; set; }
}

Notice the Invoice property that represents the relationship between this class and the Invoice class.

11. Add the following property to the Invoice class.

public ICollection<LineItem> LineItems { get; set; }

12. You'll have to instantiate the LineItems collection in the Invoice constructor.

public Invoice()
{
    LineItems = new List<LineItem>();
}

So now the Invoice class has a one to many relationship representation and the entity framework will know how to generate the correct relationship in the database.

Step 2: Create the DBContext Class

Now that we have the Invoice and the LineItem classes we need to create a class that inherits from a new object in the Entity Framework 4.1 called DBContext.  The DBContext class wraps the ObjectContext which is the main object in previous versions of the Entity Framework.  The DBContext class contains the most commonly used features using a simplified API.

1.   You'll need to add a reference to the EntityFramework to your project to use this class.  Right click on the References in the Solution Explorer and select Add References… from the pop-up menu.

2.   Select EntityFramework and System.Data.Entity from the list and click the OK button.

3.   Right click on the project file and select AddàClass…from the pop-up menu.

4.   Name the class Accounting.cs and click the Add button.

5.   Add the following code to the Accounting class.

using System.Data.Entity;
 
public class Accounting : DbContext
{
    public DbSet<Invoice> Invoices { get; set; }
    public DbSet<LineItem> LineItems { get; set; }
}

The two properties represent the two tables that will be generated in the database.

6.   Now you need to add the connection string in your web.config file so Visual Studio know where to create the database.  Add the following to the connectionStrings section in the web.config file.

<add name="Accounting" 
providerName="System.Data.SqlClient" 
connectionString=
"Data Source=(local);Initial Catalog=Accounting;Integrated Security=SSPI;"/>

The name must match the name of the class that inherits from the DBContext class.  The connection string will create a database called Accounting on the local SQL Server.  The user must have permissions to create a database on this server or you will get an error.

7.   Now we can add a GridView control to the Default.aspx page to display the data that is in the Invoices and LineItems tables.  Open the HTML Markup for the Default.aspx page and add the following.

<asp:GridView ID="GridView1" runat="server"></asp:GridView>

8.   Open the code behind page and add the following using statement.

using System.Data.Entity;

9.   Add the following code to the Page_Load event.

protected void Page_Load(object sender, EventArgs e)
{
    Accounting db = new Accounting();
 
    db.Invoices.Load();
            
    GridView1.DataSource = db.Invoices.Local.ToBindingList();
    GridView1.DataBind();
}

10. Run the project.

You should see the Default.aspx page and the GridView will be empty.  But, what you didn't see is that the Accounting database was created for you behind the scenes automatically.  Open SQL Server Management Studio and connect to your local server.  You should see the Accounting database and three tables.

The Invoices and LineItems table were created based on the class definitions and a third table called EdmMetadata, is created that the Entity Framework uses to manage the meta data in the database.  Notice in the Invoices table that the ID field was created as the Primary Key and as the Identity field.  The same is true for the LineItems table.  If you look at the design of the LineItems table you will also notice that the Invoice_ID field was added to the table automatically to hold the foreign key back to the Invoice.

Step 3: Selecting, Adding, Updating, and Deleting Records

Now that the database has been created you can add, update, and delete records using the Accounting class.  Add the following code to the Page_Load event to add an Invoice record.

protected void Page_Load(object sender, EventArgs e)
{
    Accounting db = new Accounting();
 
    Invoice invoice = new Invoice
    {
        InvoiceDate = DateTime.Now,
        Total = 1000
    };
 
    db.Invoices.Add(invoice);
    db.SaveChanges();
 
    db.Invoices.Load();
         
    GridView1.DataSource = db.Invoices.Local.ToBindingList();
    GridView1.DataBind();
}

This code creates an instance of an Invoice class and then adds it to the Invoices DBSet property of the Accounting class.  The SaveChanges method commits the changes to the database.  If you run the project again you should see the newly added record in the GridView.

Now let’s update the record we just created.  Change the code to the following.

protected void Page_Load(object sender, EventArgs e)
{
    Accounting db = new Accounting();
 
    Invoice invoice = new Invoice
    {
        ID = 1,
        InvoiceDate = DateTime.Now,
        Total = 900
    };
 
    db.Entry(invoice).State = EntityState.Modified;
 
    db.SaveChanges();
 
    db.Invoices.Load();
            
    GridView1.DataSource = db.Invoices.Local.ToBindingList();
    GridView1.DataBind();
}

This code creates an instance of the Invoice class but this time it sets the ID to 1.  It then attaches the invoice object and sets its state to Modified.  This tells the Entity Framework to update all the fields for this object.  If you run the project again you should see the updated record in the GridView control.  If you check the database you'll see that the record was updated.

Now let's delete this record.  Change the code to the following.

protected void Page_Load(object sender, EventArgs e)
{
    Accounting db = new Accounting();
 
    Invoice invoice = new Invoice
    {
        ID = 1,
        InvoiceDate = DateTime.Now,
        Total = 900
    };
 
    db.Invoices.Remove(invoice);
 
    db.SaveChanges();
 
    db.Invoices.Load();
            
    GridView1.DataSource = db.Invoices.Local.ToBindingList();
    GridView1.DataBind();
}

If you run the project you will see that the GridView control is empty and if you look in the database you'll see the table is empty.

Step 4: Changing the Model

As with most projects, you'll need to be able to modify the structure of the database.  Let's say we want to add another property to the Invoice class called Tax.  We'll need that field to be added to the database also.  The following steps will show you how to handle this situation with the Entity Framework 4.1.

1.   Add the Tax property to the Invoice database.

2.   If you run the project now without doing anything else you will get the following error.

The model backing the 'Accounting' context has changed since the database was 
created. Either manually delete/update the database, or call 
Database.SetInitializer with an IDatabaseInitializer instance. For example, the 
DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate 
the database, and optionally seed it with new data.

3.   So this is telling you that you can either manually drop the database and then the Entity Framework will automatically generate the database for you or you can add a few lines of codes so this will happen for you automatically.  We'll add the code so this happens automatically anytime the structure changes.

4.   Add the following code to the Appllication_OnStart event in the Global.asax file.

void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    System.Data.Entity.Database.SetInitializer<Accounting>
(new System.Data.Entity.DropCreateDatabaseIfModelChanges<Accounting>());
}

5.   Now run the project again.

You may get an error because some connections to the database have not been closed so the database won't be able to be dropped.  If you didn't get any errors then you should see that the Tax field has been added to the Invoice table.

Step 5: Seed the Database

Another nice feature that you get with the Entity Framework 4.1 is the ability to seed the database with data.  This is especially useful if the database is constantly changing and the structure is being dropped and recreated.  To seed the database with an invoice record do the following.

1.    Right click on the project in the Solution Explorer and select AddàClass…

2.   Name the class AccountingInitializer.cs and click the Add button.

3.   Add the following code to the AccountingInitilizer class.

public class AccountingInitializer : 
      System.Data.Entity.DropCreateDatabaseIfModelChanges<Accounting>
{
    protected override void Seed(Accounting context)
    {
        Invoice invoice = new Invoice { Total = 20, InvoiceDate = 
            new DateTime(2011, 4, 14), Tax = 1.50 };
 
        invoice.LineItems.Add(new LineItem 
            { ItemCost = 2, ProductName = "Test", Units = 4 });
 
        invoice.LineItems.Add(new LineItem 
            { ItemCost = 4, ProductName = "Test 2", Units = 3 });
            
       context.Invoices.Add(invoice);
       context.SaveChanges();
 
       base.Seed(context);
    }
}

This class inherits from the DropCreateDatabaseIfModelChanges class which was used in the previous section.  You can override the Seed method to have the framework add records to the database whenever the database is dropped and recreated.

4.   Go back to the Globals.asax code behind page and change the Application_OnStart event to the following.

void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    System.Data.Entity.Database.SetInitializer<Accounting>
      (new AccountingInitializer());
}

This now uses the AccountingInitializer class that you just created.

5.   Since the model did not change this code will not fire unless you drop the database or change the model.  Drop the database using SQL Server Management Studio and then run the project again.  Make sure you comment out the code in the Default.aspx Page_Load event that deletes the record.

After you run the project you should see that the database was recreated and the Invoices table has one record and the LineItems table has two records.

Summary

This article explained the basic concepts of the Code First features in the Entity Framework 4.1 to get you started.  There are numerous other features that allow you to add validation to your classes and even override the default implementation of how the fields are created that will be featured in a future article.

Good luck on your project and happy coding. 



©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-29 5:12:31 AM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search