Entity Framework

Add a Dropdown Filter

On my contacts application I wanted the option to only show contacts from a specific city. To accomplish this I am going to use a dropdown with a distinct list of cities that exist in my contact list.

Below is part of the existing contacts controller with the Index action that gets all contacts and returns a view.

public class ContactsController : Controller
{
    private ContactDbContext db = new ContactDbContext();

    // GET: Contacts
    public ActionResult Index()
    {
        var contacts = from c in db.Contacts
                       select c;
        return View(contacts);
    }
}

Using ContactDbContext, which is a entity framework DbContext for contacts, the database will be queried for a list of distinct cities. The list of distinct cities is then stored as a select list in the view bag.

var cityList = new List<string>();
var cityDistinct = from c in db.Contacts
                   orderby c.City
                   select c.City;

cityList.AddRange(cityDistinct.Distinct());
ViewBag.city = new SelectList(cityList);

ViewBag is a dynamic object and is one way to pass data from a controller to a view. A dynamic object basically allows you to add properties just by setting them. In the above example the with ViewBag.city is adding a city property to the ViewBag and setting it equal to a new SelectList.

The resulting index action now takes a city parameter which is used when querying for contact if it has a value.

public ActionResult Index(string city)
{
    var cityList = new List<string>();
    var cityDistinct = from c in db.Contacts
                       orderby c.City
                       select c.City;

    cityList.AddRange(cityDistinct.Distinct());
    ViewBag.city = new SelectList(cityList);

    var contacts = from c in db.Contacts
                   select c;

    if (!string.IsNullOrWhiteSpace(city))
    {
        contacts = contacts.Where(c => c.City == city);
    }

    return View(contacts);
}

In my razor view the following adds the new city filter to the UI.

@using (Html.BeginForm("Index", "Contacts", FormMethod.Get))
{
<p>
    City: @Html.DropDownList("city", 
                             ViewBag.city as SelectList, 
                             "All", 
                             new {@class = "city", 
                                  onchange = "this.form.submit();"})
</p>
}

“All” is the label used for the default empty item. The last bit is for HTML attributes and set the class for the drop down to “city” and makes it so the form submits on change of the drop down. This means that when a new city is selected the view will refresh and only show contacts for the newly selected city.

This is the resulting UI:CityFilterUi

Add a Dropdown Filter Read More »

Duplicate Records from Migration Seed

I am writing a contact management application as a vehicle for my ASP.NET MVC learning using Entity Framework 6. To pre-load some test data I utilize the Seed method found in Migrations\Configuration.cs which gets added when migrations are enabled for a project.

When testing the contact creation process I noticed that I forgot to add a property for contact’s state. Easy enough to fix. I opened up the Contact class, added the missing state property and updated all the related views. Then I ran the app to test my change and was greeted with this error:ContextChanged

Of course the model backing my DbContext has changed since the database was created, I just added a new property to the model. Being new to entity framework workflow I often see this error when I forget to update the database before running the app to try out a change. It is easy to fix by using the package manager console to Add-Migration and then Update-Database.

After updating the database I ran the app to verify my changes. What I saw when my contact list load was that all my seed data had been duplicated. The jest of my seed function was something like this:

context.Contacts.AddOrUpdate(c => c.Id,
    new Contact
    {
        Id = 0,
        Name = "Eric",
        State = "TN"
    },
    new Contact
    {
        Id = 1,
        Name = "Tommy",
        State = "ND"
    });

To track down the duplication issue the first thing I did was to view the data in the database to make sure the table a primary key set. The Id field was an integer identity column and was the primary key. Next I viewed all the records in the table which looked like this:

Id Name State
0 Eric TN
1 Tommy ND
2 Eric TN
3 Tommy ND

The Id lookup I defined as the first parameter to AddOrUpdate seemed to be my issue. From my tests it seems that AddOrUpdate will always perform an add when trying to match on an identity type column. By changing from c => c.Id to c => c.Name no data is duplicated.

Duplicate Records from Migration Seed Read More »

LocalDB v11.0 or MSSQLLocalDB

I have just started learning ASP.NET MVC 5. As a jumping off point I am working though Rick Anderson’s Getting Started with ASP.NET MVC 5. I am completely new to ASP.NET and Entity Framework and Rick’s tutorial has been a great introduction. Everything was going great until I got to the Add a New Field section.

The tutorial is using entity framework 6 to interact with an instance of SQL Express LocalDB. As part of adding a new field to an existing model Rick walks the reader through enabling code first migrations, creating an initial migration and deleting the existing database file. I completed all the steps without any issues.

The next step was to run Update-Database from the package manager console. This command failed with the message “Cannot attach the file ‘path to .mdf’ as database ‘name of database'”. After some searching I found out that using the solution explorer to manually deleting a mdf file from the App_Data directory has been known to cause problems. I restored my mdf from the recycle bin and fired up Visual Studio’s SQL Server Object Explorer and connected using a connection string of “(LocalDB)\v11.0” which I had been using in my application.

As you can see from this screenshot the only databases in this instance of LocalDB are system localdbv110databases. I ran the application and to my surprise it was working again after the restore the mdf file. I tried disconnecting LocalDB and reconnecting with the same results. I tried using the package manager to stop and delete LocalDB. None of this cleared up the problems I was having with the Update-Database command. Some of the post I can across suggested using a different database name in the application’s connection string so that a completely new database would be created, but I was only going to use that tactic as a last resort.

After more searching I came across a post that was using a different connection string localdballfor LocalDB. Instead of “(LocalDB)\v11.0” that I had seen referenced in all of the examples I had seen so far this person was using “(LocalDB)\MSSQLLocalDB”. As it turns out “(LocalDB)\MSSQLLocalDB” is the connection string used for SQL Express 2014 and “(LocalDB)\v11.0” is used for SQL Express 2012. I have both the 2012 and 2014 version installed on my machine. I am not clear on why my database was being created in the 2014 version of SQL Express when my application was using the 2012 connection string. As a fix I have updated all the connection strings in my application to the 2014 version and all is now working without any more problems.

LocalDB v11.0 or MSSQLLocalDB Read More »