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.
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.
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:
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.
Thanks for a post. I have one question as I know if I add [Key] attribute to the property i don’t need to do it again in the OnModelCreating method, so for what did you do this?
PS sorry for bad English, I am from Ukraine…
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.
-1′
Pingback: EntityFramework MySql Unable to Retrieve Metadata for | Jisku.com - Developers Network
Pingback: Unable to Retrieve Metadata