Developing ASP.NET MVC 3 Application with EF CTP (Part 1)

I this post I will walk through steps of creating an ASP.NET MVC 3 application using new code first entity framework CTP as data access and business layer.  Just a few upfront comments.  Both technologies are in preview state right now, but will likely be released in first half of next year.

To get started we have to download and install them.  To make this simpler, I will use NuGet (formerly  NuPack) which is package management software for .NET applications.  You can find it here.  Visual Studio 2010 is required to follow along with the demo, by the way.  You can download ASP.NET MVC 3.0 beta here.

Now that it has been downloaded and installed, let’s create new project.

image

Next step to pick the view engine you want to use.  You can select either ASPX (ASP.NET) or new Razor engine that will ship with MVC 3.0 and new product – Web Matrix.

image

We will go ahead and also select to create Unit Test project.

What the wizard builds for us is empty site with home view and registration service that uses membership provider.  Let’s run the app to see if everything worked correctly.  We can open web.config and verify that the system is using ASP.NET SQL Membership provider for login:

<configuration>
  <
connectionStrings
>
    <
add name=ApplicationServices

         connectionString=data source=.SQLEXPRESS;Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true

         providerName=System.Data.SqlClient
/>
  </
connectionStrings>
 
  <appSettings
>
    <
add key=enableSimpleMembership value=false
/>
    <
add key=ClientValidationEnabled value=false
/>
    <
add key=UnobtrusiveJavaScriptEnabled value=true
/>
  </
appSettings>
 
  <system.web
>
 
    <authentication mode=Forms
>
      <
forms loginUrl=~/Account/LogOn timeout=2880
/>
    </
authentication>
 
    <membership
>
      <
providers
>
        <
clear
/>
        <
add name=AspNetSqlMembershipProvider
 
            
type=System.Web.Security.SqlMembershipProvider
 
            
connectionStringName=ApplicationServices
             enablePasswordRetrieval=false
 
            
enablePasswordReset=true
 
            
requiresQuestionAndAnswer=false
 
            
requiresUniqueEmail=false
             maxInvalidPasswordAttempts=5
 
            
minRequiredPasswordLength=6
             minRequiredNonalphanumericCharacters=0
 
            
passwordAttemptWindow=10
             applicationName=/
/>
      </
providers
>
    </
membership
>

Now, let’s add our code.  Since I absolutely lack any imagination, I will create blogging application.  Each blog will contain title, text, posted date and category.  Let’s create entities for blogs and categories using EF code first CTP.  First, let’s install CTP 4 for entity framework.  To do, we will use NuGet functionality.  Right click on references node in solution and select add package, search for EF and Select EFCTP 4:

image

 

image

Now, let’s create our two classes – categories and blog posts.  We will add them to the Model folder. Blog category class is very simple:

    public class BlogCategory
    {
        [
Key
]
       
public int CategoryId { get; private set
; }
 
        [
Display(Name = “Category Name”
)]
       
public string CategoryName { get; internal set; }
 
    }

 

I made blog entries property virtual to enable lazy loading.  Blog entry class is only slightly mode complicated:

    public class BlogEntry
    {
        [
Key
]
       
public int BlogEntryId { get; private set
; }
 
        [
Display(Name = “Title”
)]
        [
StringLength
(30, MinimumLength = 5)]
        [
Required
]
       
public string Title { get; set
; }
 
        [
Display(Name = “Post Text”
)]
        [
StringLength
(30, MinimumLength = 5)]
        [
Required
]
       
public string PostText { get; set
; }
 
        [
Display(Name = “Category”
)]
       
public BlogCategory Category { get; set
; }
 
        [
Display(Name = “Post Date”
)]
        [
Range(typeof(DateTime), “1/1/1900”, “12/31/2099”
)]
       
public DateTime? PostedOn { get; set; }
    }

 

As you can see, I am using attributes from DataAnnotations namespace to describe the properties of my classes.  Next class I need is DbContext, which essentially is my database abstraction:

    public class BlogContext : DbContext
    {
       
public DbSet<BlogCategory> Categories { get; set
; }
       
public DbSet<BlogEntry> Entries { get; set
; }
 
       
protected override void OnModelCreating(

          System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
        {
           
base
.OnModelCreating(modelBuilder);
 
            modelBuilder.Entity<
BlogEntry
>().HasKey(a => a.BlogEntryId);
            modelBuilder.Entity<
BlogCategory>().HasKey(a => a.CategoryId);
 
        }
    }

 

 

As you can see I have two properties – for blog entries and categories.  I also modify default configuration of my database by overriding OnModelCreating and specifying my primary key columns and table names.  One more class I would like to add to customize database creation behavior that is very useful for development:

    public class BlogDatabase :

       System.Data.Entity.Infrastructure.RecreateDatabaseIfModelChanges<BlogContext>
    {
       
protected override void Seed(BlogContext
context)
        {
            context.Categories.Add(
new BlogCategory()

             { CategoryName = “General” });
            context.Categories.Add(
new BlogCategory()

             { CategoryName = “Entity Framework” });
            context.Categories.Add(
new BlogCategory()

             { CategoryName = “Silverlight” });
        }
    }

 

This class inherits for recreate database behavior.  I am overriding Seed method to prepopulate my database with a handful of categories.  Now, I have to register my class in global.asax.  I am doing so by setting initializer in static method on database class.

        protected void Application_Start()
        {
           
AreaRegistration
.RegisterAllAreas();
           
Database.SetInitializer<BlogContext>(new BlogDatabase
());
 
            RegisterGlobalFilters(
GlobalFilters
.Filters);
            RegisterRoutes(
RouteTable.Routes);
        }

In the next post I will add some web pages to use these classes. 

5 Comments

  1. You are correct, this is not necessary. I was illustrating various approaches to do the same thing. By the way, you can post in Russian or Ukrainian. I am from Kiev originally, I just live in Atlanta, GA, USA right now.

  2. Pingback: EntityFramework MySql Unable to Retrieve Metadata for | Jisku.com - Developers Network

  3. Pingback: Unable to Retrieve Metadata

Leave a Reply

Your email address will not be published. Required fields are marked *