About Us

Entity Splitting in Code First Entity Framework

by Travis Ellis 26. February 2013 19:51

In my last post I talked about a mapping option in Entity Framework called table splitting. Table splitting allows you to take a single physical table and split it into multiple entities in your Entity Framework model. Today I will talk about another modeling option called entity splitting.

Entity splitting gives you the ability to take a single entity in your model and split it into multiple physical database tables. It is essentially the opposite of table splitting. When you query this entity in Entity Framework, it will create a query that automatically joins to the tables for you. Consider the following entity in Code First:

public class User
{
    // these fields come from the Users table
    public int UserId { get; set; }
    public string Username { get; set; }

    // these fields come from the UserProfiles table
    public string FavoriteColor { get; set; }
    public string EmailAddress { get; set; }
}

The above model stores information about a User in our system. The UserId and Username properties will be stored in the Users table, and the EmailAddress and FavoriteColor properties will be stored in the UserProfiles table. Without adding the configuration, Code First will use the default conventions to create a single table (dbo.Users) where all 4 properties would be stored. Let's change that by overriding the default conventions:

public class EntitySplittingContext : DbContext
{
    public IDbSet Users { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity()
            // Map to the Users table
            .Map(map =>
            {
                map.Properties(p => new {
                    p.UserId,
                    p.Username
                });

                map.ToTable("Users");
            })
            // Map to the Users table
            .Map(map =>
            {
                map.Properties(p => new {
                    p.FavoriteColor,
                    p.EmailAddress
                });

                map.ToTable("UserProfiles");
            });
    }
}

We use two Map statements to select which properties go to the Users table and which properties go to the UserProfiles table. Entity Framework will create two tables in the database with a one-to-one relationship. Since we chose to have UserId belong to the Users table, it will treat that table as the Parent table. The UserProfiles table will also contain a UserId primary key column but it will not be an identity and will contain a foreign key reference back to the Users table.

As I mentioned before, when we query the Users entity the query that is generated for us will automatically perform a join between the two tables. Here is a query that demonstrates this behavior:

Entity Splitting

using(var db = new EntitySplittingContext())
{
    var users = db.Users.Where(u => u.Username == "Travis.Ellis").ToList();
}

-- SQL Query
SELECT 
[Extent1].[UserId] AS [UserId], 
[Extent1].[Username] AS [Username], 
[Extent2].[FavoriteColor] AS [FavoriteColor], 
[Extent2].[EmailAddress] AS [EmailAddress]
FROM  [dbo].[Users] AS [Extent1]
INNER JOIN [dbo].[UserProfiles] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[UserId]
WHERE N'Travis.Ellis' = [Extent1].[Username]

Table Splitting in code first entity framework

by Travis Ellis 20. February 2013 19:28

A significant benefit to using Entity Framework is that your entity model does not have to match your database model. One of the ways this is accomplished is by using Table Splitting, which is having two entities in your model map to the same physical database table.

An example of using table splitting would be if you have a Customer entity that contains details about a Customer (first name, last name, e-mail, etc.) and a separate entity to store their address. The database table might store all of this information in a single physical table, but we might not want to pull back the Address every time we want the Customer information.

To accomplish this scenario in Code First you will need the following two entity classes and DbContext configuration:

public class Customer
{
    public int CustomerID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string EmailAddress { get; set; }

    public CustomerAddress Address { get; set; }
}

public class CustomerAddress
{
    public int CustomerID { get; set; }

    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }

    public Customer Customer { get; set; }
}

public class TableSplittingContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity()
            .HasKey(pk => pk.CustomerID)
            .ToTable("Customers");

        modelBuilder.Entity()
            .HasKey(pk => pk.CustomerID)
            .ToTable("Customers");

        modelBuilder.Entity()
            .HasRequired(p => p.CustomerAddress)
            .WithRequiredPrincipal(c => c.Customer);
    }

    public IDbSet Customers { get; set; }
}

The database that gets generated from this model will have a single table in it that looks like the following: Table Splitting

Now when you write a query to retrieve a Customer it will only retrieve columns related to the Customer and not the address. If you retrieve a Customer with the Address it will generate a query that selects both sets of columns. Here is an example of both of those queries and the resulting SQL queries that get generated:

using(var db = new TableSplittingContext())
{
    var customers = db.Customers.ToList();
    var customersAndAddress = db.Customers.Include(c => c.Address).ToList();
}

-- Query 1
SELECT 
    [Extent1].[CustomerID] AS [CustomerID], 
    [Extent1].[FirstName] AS [FirstName], 
    [Extent1].[LastName] AS [LastName]
FROM [dbo].[Customers] AS [Extent1]

-- Query 2
SELECT 
    [Extent1].[CustomerID] AS [CustomerID], 
    [Extent1].[FirstName] AS [FirstName], 
    [Extent1].[LastName] AS [LastName], 
    [Extent1].[Line1] AS [Line1], 
    [Extent1].[Line2] AS [Line2], 
    [Extent1].[City] AS [City], 
    [Extent1].[State] AS [State], 
    [Extent1].[ZipCode] AS [ZipCode]
FROM [dbo].[Customers] AS [Extent1]

As you can see the first query only pulls the relevant Customer details and the second query pulls both the Customer and Address columns, all coming from a single table. This allows the queries that do not need Address information to be more efficient. In a future post I will talk about Entity Splitting, which is the opposite of table splitting in that two tables map to a single Entity in the model.

Serializing ModelState errors in a json call

by Travis Ellis 4. February 2013 01:31

In ASP.net MVC, the ModelStateDictionary class contains all of the validation errors for your models that get posted from your forms. The HTML helpers Html.ValidationSummary and Html.ValidationMessageFor will look at the Model State to display these validation messages. When you are submitting your form with an AJAX request and return a JSON response, then you need to have a way to return these validation errors to your views. Here is a helpful extension method that will allow you to do that:

public static class ModelStateExtensions
{
    public static IDictionary ToSerializedDictionary(this ModelStateDictionary modelState)
    {
        return modelState.ToDictionary(
            k => k.Key,
            v => v.Value.Errors.Select(x => x.ErrorMessage).ToArray()
        );
    }
}

Now in your controller action you can return this data back to your view:

[HttpPost]
public ActionResult Create(ProjectModel model)
{
    // Validation Errors
    if(!ModelState.IsValid)
    {
        return Json(ModelState.ToSerializedDictionary());
    }

    // Success - Save Project data
}
}

In your view you can now write some javascript code to display the errors in your view.

Injecting a dependency into an action filter using ninject

by Travis Ellis 20. November 2012 04:06

One of the most powerful features of using Inversion of Control/Dependency Injection is the ability to have highly testable code. When your dependencies are interfaces instead of concrete classes, it makes it very easy for a unit test to mock that dependency:

public class ProductsController : Controller
{
    protected readonly IProductService productService;
 
    public ProductsController(IProductService productService)
    {
        this.productService = productService;
    }

    [HttpPost]
    public ActionResult GetProducts()
    {
        return Json(productService.GetAllProducts());
    }
}

The above example shows an MVC controller that takes a single dependency: IProductService. There is a single action method that is using the service to get a list of products, which is being returned via JSON. Since the dependency is defined as an interface, the code is very easy to test with a mocking framework.

What happens when you want to apply the same concept to an Action Filter? Action Filters are attributes that are added to your controllers and actions at compile time so you can’t pass a dependency through the constructor. Well, with Ninject you can.

Using NuGet, install the Ninject.MVC3 package (also works in MVC 4). This will add both the Ninject and Ninject MVC packages and add a file  called NinjectWebCommon.cs to the App_Start folder in your solution. This is where we will set up the dependency injection for our action filters. Before we can do that we will need to create our action filter.

For this example we will create a simple filter that could be used for logging. The first thing you need to do is create a dummy attribute that you can apply to your action methods:

public enum SeverityLevel
{
    Warning,
    Information
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class LogAttribute : FilterAttribute
{
    public LogLevel Level { get; set; }

    public LogAttribute(LogLevel level)
    {
        this.Level = level;
    }
}

This can be applied to your action methods as follows:

[Log(SeverityLevel.Information)]
public Actionresult Index()
{
    return View();
}

This attribute by itself does nothing, but it will be used as a hook to inject a dependency into our real filter:

public class LogFilter : IActionFilter
{
    protected readonly ILogService logService;
    protected readonly LogLevel level;

    public LogFilter(ILogService logService, LogLevel level)
    {
        this.logService = logService;
        this.level = level;
    }

    public void OnActionExecuted(ActionExecutedContext filterContext
    {
        // implement logging logic here
        this.logService.Log(...);
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // implement logging logic here
        this.logService.Log(...);
    }
}

You can now write unit tests against the filter class and mock up your dependency using a mocking framework, but there is one more thing we need to do to wire everything that is up. Right now our filter has no direct tie to our attribute. Let’s change that by adding the following code to the NinjectWebCommon class in the RegisterServices method:

private static void RegisterServices(IKernel kernel)
{
    kernel.BindFilter<LogFilter>(FilterScope.Action, 0)
        .WhenActionMethodHas<LogAttribute>()
        .WithConstructorArgumentFromActionAttribute<LogAttribute>("level", attr => attr.Level);
}

The BindFilter is is an extension method that exists in the Ninject.Web.Mvc.FilterBindingSyntax namespace. Once you add this line whenever Ninject creates an action method that has the LogAttribute applied to it, it will automatically apply the LogFilter and inject any dependencies that it knows how to create. That is all you need to get dependency injection working on an MVC action filter.

Be Careful When Bundling Stylesheets in MVC 4

by Travis Ellis 20. August 2012 18:47

Microsoft released the newest version of the MVC framework as part of their Visual Studio 2012 release this week. One of the features of this release is the bundling and minification capabilities. Bundling allows you to combine many resources such as stylesheets and scripts so that fewer requests are made to the server. An example on using this feature is below:

public class BundleConfig {
    public static void RegisterBundles(BundleCollection bundles) {
        // combine all of the jquery ui scripts into one bundle
        bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
                "~/Scripts/jquery-ui-{version}.js"));

        // combine all of the jquery ui scripts into one bundle
        bundles.Add(new StyleBundle("~/content/themes/base/jquery").Include(
                "~/Content/themes/base/jquery.ui.core.css",
                "~/Content/themes/base/jquery.ui.resizable.css",
                "~/Content/themes/base/jquery.ui.selectable.css",
                "~/Content/themes/base/jquery.ui.accordion.css",
                "~/Content/themes/base/jquery.ui.autocomplete.css",
                "~/Content/themes/base/jquery.ui.button.css",
                "~/Content/themes/base/jquery.ui.dialog.css",
                "~/Content/themes/base/jquery.ui.slider.css",
                "~/Content/themes/base/jquery.ui.tabs.css",
                "~/Content/themes/base/jquery.ui.datepicker.css",
                "~/Content/themes/base/jquery.ui.progressbar.css",
                “~/Content/themes/base/jquery.ui.theme.css"));
    }
}

The above code creates bundles for the jQuery UI scripts and stylesheets. In order to use them in your view you do the following:

@Scripts.Render("~/bundles/jqueryui")
@Styles.Render("~/content/themes/base/jquery")

One thing you might be tempted to do when bundling your stylesheets is use a shorter name for your bundle such as "~/css/jqueryui", but there is one thing you need to be aware of when you do this. It is common for stylesheets to include references to images relative to the stylesheet directory. For example, the default jQuery UI theme is installed in the ~/Content/themes/base/ directory. Inside of that directory is an images/ folder that contains many of the sprites that jQuery UI uses. If you create a CSS bundle called "~/css/jqueryui" then you might notice that none of the jQuery UI icons work any more. This is because the content is expected to be relative to the directory that the stylesheet is in. When creating the bundle as ~/css/jqueryui, the images are expected to be in ~/css/images.

Unless you are running with debug=”false”, you might not even notice the problem. This is because by default, when running with debug=”true”, the ASP.net runtime will still make separate requests for every resource in your bundle. When changing to debug=”false”, ASP.net will actually combine all of the files in your bundle and make a single request (per bundle). The request might look similar to:

<link href="/css/jqueryui?v=ps9Ga9601PrzNA2SK3sQXlYmNW3igUv5FOdOPWptyus1" rel="stylesheet"/>

Since the request is being made to /css/jqueryui, the server expects that any relative paths are going to be relative to the /css directory. To fix this, you need to make sure your CSS bundle names are similar to the physical directory structure of your application. When installing the jQuery UI nuget package, it will put your stylesheets in the directory /content/themes/base/ so you should name your bundle "~/content/themes/base/jqueryui" to make sure that everything works.

Working with events in jquery 1.7

by Travis Ellis 19. June 2012 00:22

jQuery is a great javascript library that makes it easy to do many common tasks in a web application. One of the most frequent things you need to do is wire up events to your DOM elements. Prior to jQuery 1.7, you had a few different ways to accomplish this:

Option 1: Using the Bind method

<script type="text/javascript">
    $("a.add").bind("click", function(event) {
        alert("You clicked a link.");
    });
</script>

The above code will attach a click event handler to all anchor elements that have the class “add”. Similar to this method, jQuery provides some helper methods to attach these events in a more concise syntax. When attaching the '”click” event, you can use the click() method, etc.:

<script type="text/javascript">
    $("a.add").click(function(event) {
        alert("You clicked a link.");
    });
</script>

Option 2: Using Live/Delegate

The problem with using the bind method is that it does not add event handlers to dynamically added DOM elements. In order to do this you have to use the live/delegate syntax:

<script type="text/javascript">
    $("a.add").live("click", function(event) {
        alert("You clicked a link.");
    });

    $("#parent").delegate("a.add", "click", function(event) {
        alert("You clicked a link.");
    });
</script>

This attaches a click event handler to all anchor elements that have the class "add" similar to bind. The difference, however; is that any elements that are added to the DOM dynamically will also have the event handler attached. To demonstrate the problem you can visit the following pages (you may need to click the Run button to run the example):

Adding events with the bind method
Adding events with the live function.
Adding events with the delegate function.

You’ll notice that in the first example, when you click the initial paragraph it will add another paragraph directly after it, however; if you click one of the dynamically created paragraphs they will not add additional paragraphs. This is different from the second example where clicking on the dynamically generated paragraph will also cause a new paragraph to be created. I am using delegate in this example but it also works with the live method. The only difference between delegate and live is performance. The live method will search the entire DOM for elements where as the delegate method can search specific parts of the DOM using a selector.

Option 3: Using the on method in jQuery 1.7

So why is there a need for another way to wire up events? Simplicity. In jQuery 1.7 they have made it even easier to do. They have added a new method that will allow you to wire up events like bind and live/delegate all using a single method. Instead of having to remember the syntax of three different methods, you can now use the following:

<script type="text/javascript">
    $("#parent").on("click", "a.add", function(event) {
        alert("You clicked a link");
    });
</script>

This syntax is very similar to live and it works just like delegate, but it performs better than both of them. There is also a corresponding method called off that you can use to disable the events:

<script type="text/javascript"> 
    $("#parent").off("click", "a.add");
</script>

Adding events with the on method

Add a Metadata Property to User Profiles in SharePoint 2010

by Jess Collicott 13. April 2012 04:54

In this example, our pretend company has decided it would be beneficial for the culture if employees knew how to better work with and relate to each other as they take on and complete projects. To do this, the company decided to focus on a strengths-based culture, to better allow each person's passions drive them to success. One of the methods used to help employees know their own strengths and the strengths of others was having each individual take the Clifton StrengthFinders assessment, to discover their top five strengths. Knowing employees were going to be taking and completing the assessments, the leaders at the company would like each individual to be able to populate their user profile on SharePoint 2010 with these strengths.

Within SharePoint 2010, the list of strengths were added to a Managed Metadata Term Store, so that the spelling and usage of the strengths would be consistent across all of the user profiles:

Term-Store

The following are the steps that would be used to add a property to each person's user profile so that they could assign terms from the Strengths Term Store, and show them on their individual profile.

Create the User Profile Property

Open SharePoint Central Administration, and access the User Profile Service Application by following these steps:

  1. Under Application Management, click Manage service applications
  2. Find the desired User Profile Service Application in the list, and click to highlight it
  3. Click Manage in the Ribbon

On the following page, under People, click Manage User Properties:

Managed_Properties_Link

On the Manage User Properties page, click New Property:

New_Property_Link

In the first section, provide the desired Property Settings. In this example, we will choose the name of "CliftonStrengths", and the Display Name of "Strengths". We will choose a multi-value string, with up to 150 characters. The last field maps the property to the managed terms that were previously created in the Term Store.

Property_Settings

For the Sub-type of Profile, make sure the profiles are selected that you would like to display the property on. In this case, we only have the Default Profile:

Profile_Type

Under User Description, we will provide a description that will help people understand what the intended purpose of the property is for as they are editing their profile:

User_Description

For the Policy Settings, we will choose Required for the Policy Setting, and default the visibility to Everyone.

Policy_Settings

For the Edit Settings section, we need to make sure we allow employees to edit the property's values:

Edit_Settings

On the Display Settings section, we need to show the property on the user profile page. We also need to allow the property to show up to 5 values before being shortened with an ellipsis. To be able to edit the field, we need to allow the property to be shown on the Edit Details page. We also will allow updates to the property to show in the newsfeed.

Display_Settings

After these values are set, click OK to create the new user profile property.

Custom_Properties

 

Move to the Desired User Properties Section

As shown in the last step, the new Strengths property will be displayed under a section called "Custom Properties". We want to change this so the property shows in the "Details" section. To do this, click the blue "up" arrow next to the name of the property until it is in the desired section.

Order

 

Edit the User Profile

The property is now ready to be used on the SharePoint user profiles. Navigate to your profile, and click "Edit My Profile":

Edit_My_Profile

Scroll down to the "Details" section, and either type or select the five strengths to be listed on the profile:

Select_Strengths

Click Save and Close.

Then, on the user profile click the link titled "More Information":

More_Information_Link

The user profile should then show the "Strengths" property, with the selected strengths for the individual.

Final

A Quick Introduction to Fluent Validation in ASP.net MVC

by Travis Ellis 2. April 2012 20:03

In one of the projects I am working on we are using ASP.net MVC for our web front-end. I love the framework but I have never really been thrilled about validation using the DataAnnotations library. Based on the recommendation of some other people I discovered the FluentValidation library. The goal of this post is to show you how to create a very simple MVC application using FluentValidation as an alternative to DataAnnotations.

The first thing you need to do is create a new MVC Application using Visual Studio 2010:

image

The template you choose does not matter but for this post I am using the Internet Application template. There won’t be any authentication in the application so the Intranet template will work fine too.

Once the project is created right-click on the References item in Solution Explorer and click Manage NuGet Packages (if you do not see this menu then make sure you download the most recent version of NuGet from NuGet.org):

image

This will bring up the Package Manager dialog. In the Search box, type in FluentValidation and hit Enter. You should see a few packages in the results list. The one you want to add to the project is FluentValidation.MVC3. This will install the FluentValidation MVC3 package and FluentValidation itself (the MVC3 package depends on it). Select the FluentValidation.MVC3 package in the list and click the Install button:

image

Once the assemblies are added to the Solution, you can close the Package Manager and open the Global.asax file in the root directory of your project. You need to add a single line to your project to configure the framework to work with MVC. In the Application_Start method in Global.asax, add the following line:

FluentValidation.Mvc.FluentValidationModelValidatorProvider.Configure();

Once you have done this we can create a new Model class that will be used by one of our Views/Controllers:


public class RegistrationModel
{
    public string Username { get; set; }
    public string Password { get; set; }
    public string ConfirmPassword { get; set; }
    public DateTime BirthDate { get; set; }
    public int NumberOfChildren { get; set; }     
}

This is a simple model used to register for a website. It asks for a username, password (with confirmation), date of birth and number of children. Now that we have a model we can create the controller actions for it. We will need a GET and POST action:


[HttpGet]
public ActionResult Create()
{
    return View();
}

[HttpPost]
public ActionResult Create(RegistrationModel model)
{
    if(!ModelState.IsValid)
    {
        return View(model);
    }
    
    // register here

    return RedirectToAction("Index", "Home");
}

The code here is pretty bare and more than likely identical to the code that would be used when using DataAnnotations to do the validation. If you were to run the code right now there would be no validation. Let's fix that by creating a new validator class:


public class RegistrationValidator : AbstractValidator
{
    public RegistrationValidator()
    {
        RuleFor(model => model.Username)
            .NotEmpty()
            .Length(1, 256);

        RuleFor(model => model.Password)
            .NotEmpty()
            .Length(1, 50);

        RuleFor(model => model.ConfirmPassword)
            .NotEmpty()
            .Equal(model => model.Password);

        RuleFor(model => model.DateofBirth)
            .GreaterThanOrEqual(DateTime.Today.AddYears(-18));

        RuleFor(model => model.NumberOfChildren)
            .NotNull()
            .GreaterThan(0)
            .NotEqual(13);
    }
}

We have defined the following rules for our model:

  • Username is required and must be between 1 and 256 characters long.
  • Password is required and must be between 1 and 50 characters long.
  • Password confirmation is required and must match the password.
  • The Date of Birth must be greater than or equal to todays date 18 years ago (to confirm they are 18 or older).
  • User must have at least one child but can not have 13 (we are very superstitious).

Now that we have our validations in place, we need to update our model to include an attribute that will wire up the validation with MVC. Add the following attribute to our RegistrationModel class:


[Validator(typeof(RegistrationModel))]
public class RegistrationModel

That is all that is needed to use FluentValidation. The same rules apply when using client side validation. You need to include jQuery, jQuery Validation and optionally include jQuery Unobtrusive Validation scripts. These steps are no different than using DataAnnotations so it's very simple to convert a site to use the framework. If you are using Dependency Injection then you can also create your own validator factory that will wire up the validators for you so you don't need to register the type of validator on each model you create. If you use Ninject, there is already a NuGet package that has a validator factory that you can use. Just open up the NuGet package manager and search for Ninject.Extensions.FluentValidation.

FluentValidation is a very powerful framework. There are plenty of built in validators that you can use such as verifying a credit card or e-mail address. Creating your own custom validators is also very simple. Head on over to the CodePlex page today and look at the documentation to start using it in your projects.

Table Valued Parameters with Entity Framework

by Travis Ellis 16. November 2011 12:00

I recently worked on a project where I was calling a WCF service that returned a collection of values that had a Name and a Type. I needed to use that list to select values from another database using Entity Framework.  A typical result set from the WCF service looked like this:

var list = new List<NameAndType>
{
    new NameAndType { Name = "ABC", Type = "123" },
    new NameAndType { Name = "ABC", Type = "456" },
    new NameAndType { Name = "DEF", Type = "123" },
    new NameAndType { Name = "DEF", Type = "123" }
};

In a local database I had a table that had a composite primary key made up of Name and Type. I needed to write a query that took this list of name/type values and found matching rows in my database. This would be a simple thing to do if I had a single value as my key. If that were the case I could have written a query like this:

var list = List<string>
{
    "ABC",
    "DEF"
};
    
var items = from i in context.Items
            where list.Contains(i.Name)
            select i;

The above query will translate into a statement similar to SELECT * FROM Items WHERE Name IN ('ABC', 'DEF'). The problem is that I had two properties that I needed to predicate on. I wasn't sure how to write the query in Entity Framework but my first thought was something like the following:

var list = new List
{
    new NameAndType { Name = "ABC", Type = "123" },
    new NameAndType { Name = "ABC", Type = "456" },
    new NameAndType { Name = "DEF", Type = "123" },
    new NameAndType { Name = "DEF", Type = "123" }
};

var result = from a in context.Items
             join b in list
             on new { a.Name, a.Type } equals new { b.Name, b.Type }
             select a; 

This query threw an error complaining that only primitive types could be used. I tried a few more queries but I could not figure out a way to do this. I started to think about how I would actually accomplish this in SQL using a stored procedure and settled on using a Table-Valued Parameter (which I have blogged about before). At first I thought I was going to need to write a stored procedure and call that from Entity Framework, but after doing a little testing I was able to come up with a solution that allowed me to do this using an Entity Framework query:

DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Type"< typeof(string));

list.ForEach(l => dt.Rows.Add(l.Name, l.Type));

SqlParameter tableParameter = new SqlParameter("@Ids", SqlDbType.Structured);
tableParameter.TypeName = "dbo.NameAndType";
tableParameter.Value = dt;

var items = context.Database.SqlQuery<Item>(
    "SELECT * FROM dbo.Items items " +
    "INNER JOIN @Ids ids ON items.Name = ids.Name " +
    "AND items.Type = ids.Type", tableParameter);

The code creates a DataTable and adds a row for each item in my list of NameAndType values. It then creates a SqlParameter with SqlDbType of Structured and gives it a TypeName of dbo.NameAndType and a value of the table. I then created an Entity Framework query using the Database.SqlQuery<T> method which allows you to execute some SQL code. I select from my table and join to my table valued parameter and was able to get the items from my database.

One thing to note with this approach is that all of the items returned from the query will not be tracked by Entity Framework. If you need Entity Framework to track the entities you would have to do something similar to this:

foreach ( var item in items ) {
    db.Items.Attach(item);
}

In Summary

This concludes my post on writing an Entity Framework query that uses a table-valued parameter. If you have any questions, feel free to contact me with any questions.

Creating a Cascading Dropdown in ASP.net MVC 3 and jQuery

by Travis Ellis 5. August 2011 09:00

One of the common tasks that comes up when developing web applications is working with dependent data. If you have a form in your application that asks the user to select the Make and Model of their car, then you need to refresh the list of Models every time the Make changes. In ASP.net Web Forms this was commonly done by setting the AutoPostBack property of the DropDownList control and creating a SelectedIndexChanged event handler. The problem with this approach is that the page does a full postback, which can often be inefficient and can appear slow to the user. Fortunately, a better method exists in ASP.net MVC that is easy to accomplish with jQuery.

In order to show you how to create a cascading dropdown I am going to create a very simple web application. It will have a single page that will have two dropdowns, one for a list of States and one for a list of Cities. The list of Cities will change whenever the State changes. Here is the main controller for our application:

public class HomeController : Controller
{
    private ILocationRepository locationRepository = new LocationRepository();

    public ActionResult Index()
    {
        var model = new IndexViewModel();

        model.AvailableStates = new SelectList(locationRepository.GetStates(), "Abbreviation", "Name");
        model.AvailableCities = new SelectList(locationRepository.GetCities(), "Id", "Name");

        return View(model);
    }
}

public class IndexViewModel
{
    public IndexViewModel()
    {
        AvailableStates = new SelectList(Enumerable.Empty<State>(), "Abbreviation", "Name");
        AvailableCities = new SelectList(Enumerable.Empty<City>(), "Id", "Name");
    }

    public string State { get; set; }
    public int City { get; set; }

    public SelectList AvailableStates { get; set; }
    public SelectList AvailableCities { get; set; }
}

The view for our page will be extremely simple. It will consist of the two dropdown lists needed to display the data and a bit of javascript used to retrieve the data.

@model CascadingDropdowns.Models.IndexViewModel
@using (Html.BeginForm())
{
    <div class="editor-label">
        @Html.LabelFor(m => m.State)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(m => m.State, Model.AvailableStates, new { style = "width: 150px" })
    </div>
    
    <div class="editor-label">
        @Html.LabelFor(m => m.City)
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(m => m.City, Model.AvailableCities, new { style = "width: 150px" })
    </div>
    
    <p>
        <input type="submit" value="Submit" />
    </p>
}

I am holding off on posting the javascript code until I post the code to retrieve the locations. The view is pretty simple. It defines a label and a dropdown for both the State and City property of our model. It uses the AvailableStates and AvailableCities properties as the data source for the dropdowns. It also contains a Submit button to POST the form, but this example won't be doing anything when the form is posted.

Here is the controller we will use to retrieve our location data. It has two action methods that both return JSON formatted data. The first method will return a list of all states. The other method will retrieve all of the cities based on the state abbreviation that is passed in.

public class LocationsController : Controller
{
    private ILocationRepository locationRepository = new LocationRepository();

    [HttpPost]
    public ActionResult States()
    {
        var states = locationRepository.GetStates();
            
        return Json(new SelectList(state, "Id", "Name"));
    }

    [HttpPost]
    public ActionResult Cities(string abbreviation)
    {
        var cities = locationRepository.GetCities(abbreviation);

        return Json(new SelectList(cities, "Abbreviation", "Name")); 
    }
}

Here is the corresponding repository class that will retrieve the data. I am going to hard code the data to simplify the example, although it would be easy to hook up this code to a database using your favorite data access tool such as Entity Framework or LINQ to SQL.

public class LocationRepository : ILocationRepository
{
    public IQueryable<State> GetStates()
    {
        return new List<State>
        {
            new State { Abbreviation = "NE", Name = "Nebraska" },
            new State { Abbreviation = "NC", Name = "North Carolina" }
        }.AsQueryable();
    }

    public IQueryable<City> GetCities(string abbreviation)
    {
        var cities = new List<City>();
 
        if (abbreviation == "NE")
        {
            cities.AddRange(new List<City> {
                new City { Id = 1, Name = "Omaha" },
                new City { Id = 2, Name = "Lincoln" }
            });
        }
        else if (abbreviation == "NC")
        {
            cities.AddRange(new List<City> {
                new City { Id = 3, Name = "Charlotte" },
                new City { Id = 4, Name = "Raleigh" }
            });
        }

        return cities.AsQueryable();
    }
}

public interface ILocationRepository
{
    IQueryable<State> GetStates();
    IQueryable<City> GetCities(string abbreviation);
}

Now that we have a controller action that will return the data we need, it is time to wrap it all up with our jQuery code. You might have noticed that our controller actions have been marked with the [HttpPost] attribute. This will prevent the browser from caching the data, and MVC doesn't allow JSON GET requests by default. Here is the jQuery code:

<script type="text/javascript" src="/Scripts/jquery-1.5.1.min.js"></script>
<script type="text/javascript">
    function getCities(abbr) {
        $.ajax({
            url: "@Url.Action("Cities", "Locations")",
            data: {abbreviation: abbr},
            dataType: "json",
            type: "POST",
            error: function() {
                alert("An error occurred.");
            },
            success: function(data) {
                var items = "";
                $.each(data, function(i, item) {
                    items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
                });

                $("#City").html(items);
            }
        });
    }

    $(document).ready(function(){
        $("#State").change(function() {
            var abbr = $("#State").val();

            getCities(abbr);
        });
    });
</script>

That is all the code that is required to get a cascading dropdown. The jQuery code sets up an event handler that will run whenever the selected item is changed, making an AJAX call that is expecting JSON formatted data. When the AJAX call successfully completes it iterates over the collection of objects building an <option> element for each one and sets the HTML of the dropdown to the new list of items. It would be trivial to replace the code in the repository to retrieve data from a database as well, but I will leave that as an exercise for the reader.