RSS 2.0
# Thursday, January 20, 2011

Ok, well, for whatever reason, I wasn’t able to get the old project working with MvcScaffolding after updating to the RTM of MVC 3.  I had even run the upgrade tool.  We are and were dealing with beta software, sometimes that’s what happens.  Thankfully we weren’t too far along.  So, what I’ve done is created a new project and simply added all our model classes to the new project.

I then reinstalled our packages from NuGet:

image

image

Now we will do some scaffolding.

image

Change the default route to point to our Recipe Controller:

image

And wa-la, we’ve got a running application.

image

Since we never defined a connection string for the application, it created a new database in our Sql Server Express instance with the fully qualified name of the context class.

image

So you can see that outside of create our model classes, everything else can be automated and done very quickly.  Understanding what is actually going on is important, so next we’ll look in more detail at the files that were created.

Technorati Tags: ,
Thursday, January 20, 2011 10:52:44 PM UTC  #    Comments [0] -
.NET | Entity Framework | mvc | SQL Server | Visual Studio
# Wednesday, January 12, 2011

Ok, so maybe that’s not correct … do Roman numerals even have decimals.  Hmmm… maybe I should have paid a bit more attention in that class. In Part I we set up our classes and data access “layer”.  Thanks to ErikEJ letting me know of a provider that he – uh – provided for SQL CE, we’ll integrate that in.  Since this wasn’t in the original plan, we’ll call this I.V or 1.5.  Smile

You can go get the files from here.  I’m just going to include the files rather than the binary.  I found an issue in the SqlCeMembershipUtils.cs file in the CreateDatabaseIfNeeded method.  It has to do with how the path shows up.  When checking for the file, the connection returns the following for the Database (path) property, which of course is not the path to the actual sdf file.  The connection works however.

image

So, I’ve modified that method like so:

        public static void CreateDatabaseIfRequired(string connection)
        {
            string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory") as string;
            string physConnectionString = connection.Replace("|DataDirectory|", dataDirectory);
            string[] parts = connection.Split('|');
            string physFileString = Path.Combine(dataDirectory, parts[parts.Length - 1]);

            string sdfPath = string.Empty;
            lock (_lock)
            {
                using (var testConn = new SqlCeConnection(physConnectionString))
                {
                    sdfPath = testConn.Database;
                }
                if (string.IsNullOrWhiteSpace(sdfPath))
                    return;

                if (!System.IO.File.Exists(physFileString))
                {
                    //OK, try to create the database file
                    using (var engine = new SqlCeEngine(connection))
                    {
                        engine.CreateDatabase();
                    }
                }
                ValidateDatabase(connection);
            }
        }

You will of course need to modify the connections in web.config for the membership provider and add using System.IO; to the top.  The other option would be to skip the file check and just eat the exception if it’s because of the file already existing.

Technorati Tags: ,
Wednesday, January 12, 2011 7:42:48 PM UTC  #    Comments [2] -
Entity Framework | mvc
# Saturday, January 08, 2011

If you haven’t already, go install mvc 3 RC.  This will also install NuGet which we will be using.  You can read more about mvc 3 and NuGet on ScottGu’s blog.

Create a new MVC 3 Web Application and use Razor for the view engine.  Probably a good idea to tick on the unit test box to create unit tests.

image

Next get the Package Manager Console open.  View | Other Windows | Package Manager Console

Now we want to install the Entity Framework Code First libraries.  NuGet makes this very easy:

image

The console window support auto-completion, so just type Ins [TAB] and a list of options will show. Choose Install-Package then type EFC [TAB] to choose through a list of packages.  Couldn’t be easier.  I’m not going to go into details about what that does, you can read all about it in ScottGu’s posts and the video of Scott Hanselman’s talk.

In our first post in the series, our first goal was to make a quick site.  Doing it quickly means we are going to let the Entity Framework create the database for us.  We will also be using SQL CE so there won’t be a full database dependency.  SQL CE 4.0 is now bin deployable, so we can just copy it up and it’ll work.

EF, much like MVC, uses convention over configuration.  So, since our context (code to follow) is going to be named Cookbook, if we create a connection string entry called Cookbook, EF will automatically use that.

  <connectionStrings>
    <
add name="Cookbook" connectionString="Data Source=|DataDirectory|KimmysCookbook.sdf" providerName="System.Data.SqlServerCe.4.0"
/>
  </
connectionStrings>

As an aside, if you don’t create a connectionstring at all, EF CTP5 will create a Sql Server CE 4.0 database under the App_Data directory for you using the fully qualified type name as the name of the database.

Now for our Context class.  We’ll create each of our supporting classes as we go.  Right click on the Models folder and add a class.  As you are typing, as you put in the classes for the generic collections, pressing Ctrl-. will present you with a context of options.  Since the classes won’t exist yet, you can have VS create the classes for you right then.  They will of course be empty, but the shell is there.  VS is also intelligent enough to put them in the same folder as the current class with the same namespace.  So, when you type public DbSet<Recipe, you’ll get a squiggly saying that Recipe doesn’t exist.  Ctrl-. and choose to have it create the class for you.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace KimmysCookbook.Models
{
    public class Cookbook : DbContext
    {
        public DbSet<Recipe> Recipes { get; set; }
        public DbSet<Ingredient> Ingredients { get; set; }
        public DbSet<Comment> Comments { get; set; }
        public DbSet<Favorite> Favorites { get; set; }
        public DbSet<Tag> Tags { get; set; }
        public DbSet<Rating> Ratings { get; set; }
    }
}

The above context class is all that is needed for data access.

Let’s fill in the rest of our classes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace KimmysCookbook.Models
{
    public class Recipe
    {
        public int ID { get; set; }
        public Guid UserID { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public long PrepTime { get; set; }
        public long CookTime { get; set; }
        public int Serves { get; set; }
        public string Instructions { get; set; }
        public string IPAddress { get; set; }

        public virtual ICollection<Ingredient> Ingredients { get; set; }
        public virtual ICollection<Tag> Tags { get; set; }
        public virtual ICollection<Comment> Comments { get; set; }
        public virtual ICollection<Rating> Ratings { get; set; }
        public virtual ICollection<Favorite> Favorites { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KimmysCookbook.Models
{
    public class Ingredient
    {
        public int ID { get; set; }
        public int RecipeID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KimmysCookbook.Models
{
    /// <summary>
    /// This is for user based tagging
    /// </summary>
    public class Tag
    {
        public int ID { get; set; }
        public int RecipeID { get; set; }
        public Guid UserID { get; set; }
        public string Value { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KimmysCookbook.Models
{
    public class Comment
    {
        public int ID { get; set; }
        public int RecipeID { get; set; }
        public Guid UserID { get; set; }
        public string Text { get; set; }
        public string IPAddress { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KimmysCookbook.Models
{
    /// <summary>
    /// This is to tag a recipe as a favorite for a user
    /// </summary>
    public class Favorite
    {
        public int ID { get; set; }
        public int RecipeID { get; set; }
        public Guid UserID { get; set; }
        public DateTime DateFavorited { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KimmysCookbook.Models
{
    public class Rating
    {
        public int ID { get; set; }
        public int RecipeID { get; set; }
        public Guid UserID { get; set; }
        public int Value { get; set; }
        public DateTime RatingDate { get; set; }
        public string IPAddress { get; set; }
    }
}

You’ll notice in the classes that the UserID field is a Guid. In this iteration, we are going to use the Membership provider that is baked into asp.net. In a future release, we plan to use OpenID instead. That being said and to keep it simple, we want to have the membership baked into the database that EF is going to create.  Unfortunately, SQL CE 4 still doesn’t support stored procedures so the current implementation of membership won’t work with it.  According to ScottGu’s post, they are looking into create a set of providers that will work with it. 

Technorati Tags: ,
Saturday, January 08, 2011 8:22:55 PM UTC  #    Comments [2] -
.NET | Entity Framework | mvc | SQL Server
Archive
<February 2012>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2012
George Handlin
Sign In
Statistics
Total Posts: 51
This Year: 0
This Month: 0
This Week: 0
Comments: 9
All Content © 2012, George Handlin
DasBlog theme 'Business' created by Christoph De Baene (delarou)