Site Meter
 
 

Monthly Archives: January 2011

MvcScaffolding: One-to-Many Relationships

This post is part of a series about the MvcScaffolding NuGet package:

  1. Introduction: Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package
  2. Standard usage: Typical use cases and options
  3. This post: One-to-Many Relationships
  4. Scaffolding Actions and Unit Tests
  5. Overriding the T4 templates
  6. Creating custom scaffolders
  7. Scaffolding custom collections of files

Recently I’ve been adding features at a frantic pace, the most significant of which is support for relationships between entities. This means you can quickly create Create-Read-Update-Delete (CRUD) interfaces with drop-down lists, for example to set which “category” a “product” is in, or who is the “manager” or an “employee”.

Installing or Upgrading MvcScaffolding

The features I describe in this post are available in MvcScaffolding 0.9.4 or later. If you already have a previous version installed (find out by typing Get-Package into the NuGet console), you can upgrade it as follows:

Update-Package MvcScaffolding

After upgrading, you must restart Visual Studio, otherwise the old version will still be loaded into the VS appdomain, and bad things will happen. Restart Visual Studio now!

If you’ve never installed MvcScaffolding into your project, install it by entering the following into the NuGet Package Manager Console:

Install-Package MvcScaffolding

Defining simple relations between model classes

I’m going to continue the tutorial in the introductory post, which assumes you’ve already installed created the following model class:

public class Team
{
    public int TeamId { get; set; }
    [Required] public string Name { get; set; }
    public string City { get; set; }
    public DateTime Founded { get; set; }
}

Now I’d like to define another model class, Player. Each Player is associated with a team:

public class Player
{
    public int PlayerId { get; set; }
    public string Name { get; set; }
 
    // Having a property called <entity>Id defines a relationship
    public int TeamId { get; set; }
}

Simply having the TeamId property on Player is enough for both MvcScaffolding and EF Code First to realise there’s a 1:many relationship. Actually MvcScaffolding supports two conventions for defining relations – this is the simple one; I’ll explain the alternative later.

Note that defining TeamId as a non-nullable int, it’s mandatory. Each player must be in a team. If you wanted the relationship to be optional, use a nullable link property instead (i.e., public int? TeamId { get; set; }).

If you scaffold your UI now, by executing the following commands…

Scaffold Controller Team -Force
Scaffold Controller Player

(note the –Force parameter tells scaffolding to overwrite anything you already had for Team)

… then you can go to the URL /Teams and create, read, update, delete teams:

image

… and then you can go to the URL /Players and do the same for players. When you’re creating or editing a player, you’ll get a drop-down list to choose a team:

image

So, how does this work? How can the Edit action know what teams to offer in the dropdown? MvcScaffolding has created a PlayersController in which the Create/Edit actions send a list of PossibleTeams to the view to be rendered in a dropdown:

// This is in PlayersController
public ActionResult Create()
{
    ViewBag.PossibleTeams = context.Teams;
    return View();
}

If you wanted to filter the available teams in some way, you could easily edit this and put a .Where(team => somecondition) clause on the end. Scaffolding isn’t supposed to generate a finished application; it just gives you a useful starting point very quickly!

Showing relationships on Index and Details views

Right now, the Index and Details views don’t show any information about relationships. The list of teams doesn’t tell you about players:

image

… and the list of players doesn’t tell you about teams:

image

The reason no relations are shown is that neither the Team nor Player class has a property to hold instances of the related entities, so there’s nowhere to get the information from. We can improve the situation by telling Player to have a property that holds its Team:

public class Player
{
    public int PlayerId { get; set; }
    public string Name { get; set; }
    public int TeamId { get; set; }
 
    public virtual Team Team { get; set; } // This is new
}

… and by telling Team to have a property that holds its Players:

public class Team
{
    public int TeamId { get; set; }
    [Required] public string Name { get; set; }
    public string City { get; set; }
    public DateTime Founded { get; set; }
 
    public virtual ICollection<player> Players { get; set; } // This is new
}

Notice that both of these new properties are marked virtual. This lets Entity Framework use its Lazy Loading feature so the associated entities will be fetched as needed, and spares you having to write code to fetch them in your controller. I’ll talk more about this in a moment.

Now if you were to scaffold the UI with models like this, by issuing the following commands:

Scaffold Controller Team -Force
Scaffold Controller Player -Force

… then you’d find the list of teams now states how many players are associated with each:

image

…and the list of players now states which team each player belongs to:

image

Similarly, if you go onto the other views (Details, Delete, etc.), you’ll see the related model objects displayed there too:

image

This is probably exactly what you expected to see. But pause for a moment and consider: when we want to display a related model object in a grid or in a details view, how do we know how to represent that other object as a string? There could be many properties on “Team” – how do we know which one to display in the Players grid?

The answer is that MvcScaffolding uses its own conventions to go looking for a property with a likely name: Name, Title, Surname, Subject, Count. If there’s no matching property, we fall back on using ASP.NET MVC’s Html.DisplayTextFor helper. If you don’t agree with the property it chose, you can either:

  • Put a [DisplayColumn] attribute on your model class. For example, by putting [DisplayColumn("SomeProperty")] right before “public class Team…” and then rerunning the scaffolder, you’ll cause it to choose the property SomeProperty, if there is one.
  • Or, modify the T4 template to specify your own conventions (see the forthcoming post for info about customising T4 templates)
  • Or, just edit the generated views and change them! This is the easiest and best choice normally. Remember, scaffolding just gives you a quick starting point. It’s up to you to work on the code to meet all your own application’s requirements.

Eager Loading and SELECT N+1

If you’ve used ORMs before, then when you heard me talk about lazy loading you probably caught the scent of possible blood. If the Player’s “Team” property is marked virtual and hence lazy loaded, then when we display the grid of Player entities, does rendering each row cause us to issue yet another SQL query to fetch the Team for that Player? That, by the way, is called a “SELECT N+1” problem and leads to serious performance issues.

Fortunately, when the scaffolder generates your Index actions, it anticipates this and instructs EF to “eager load” all the related entities up front in a single SQL query. Example:

// This is on PlayersController
public ViewResult Index()
{
    return View(context.Players.Include(player => player.Team).ToList());
}

If your model has multiple relations, they will all be eager loaded for the grid. However, we don’t eager load for the other actions (Edit, Create, etc.) because there’s no scale problem with those – you’re only loading a single entity, and the code is easier to understand if we use normal lazy loading in those cases.

It also works when you’re generating repository classes, too, by the way. If you were to build everything with repositories like this:

Scaffold Controller Team -Repository -Force
Scaffold Controller Player -Repository -Force

… then your controllers would have constructors that receive all of the repositories they need, e.g.:

public PlayersController(ITeamRepository teamRepository, IPlayerRepository playerRepository)
{
    this.teamRepository = teamRepository;
    this.playerRepository = playerRepository;
}

… and the Index actions would still eager-load relations, using a slightly different syntax that the repository interface understands:

// This is on PlayersController
public ViewResult Index()
{
    return View(playerRepository.GetAllPlayers(player => player.Team));
}

You can thank Scott Hanselman for this feature of doing eager loading automatically. He hassled me about it yesterday, so here it is :)

Defining more complex relations between model classes

Depending on what data access technology you’re using, there may be many possible ways of defining how models are related together. If you’re using EF Code First, for example, you could be using its fluent configuration interface, which means writing code with statements like “someEntity.HasOptional(x => x.Players).WithForeignKey(x => x.TeamId).CascadeDelete()” and so on.

MvcScaffolding doesn’t know about all of that. For one thing, fluent configuration exists only at runtime (and scaffolding works at design time), and for another, you might be using any data access technology with its own configuration system. You can still use fluent configuration or anything else; just don’t expect scaffolding to know about it.

Instead, MvcScaffolding supports two simple and broadly applicable conventions that will work fine with most data access technologies, including EF.

(1) You can define a simple parent relation to the model class <SomeEntity> by adding a property called <SomeEntity>Id, as you’ve already seen:

public class Player
{
    public int PlayerId { get; set; }
    public string Name { get; set; }
 
    // This links Player to Team
    public int TeamId { get; set; }
}

Note that if you also have a Team property on Player (as in the code earlier), EF recognizes this convention and populates Team with the entity specified by TeamId. Scaffolding, however, doesn’t need to know or care about this: it just displays Team information in Player views because that property is there.

(2) You can define a complex parent relation by adding a property called <Anything>Id, plus another property called <Anything> that defines the type of the relation. For example, you could make Team objects reference other Team objects, or multiple Person objects:

public class Team
{
    public int TeamId { get; set; }
    // ... other Team properties go here
 
    // Each Team has an optional "next opponent" which is another Team
    public int? NextOpponentId { get; set; }
    [ForeignKey("NextOpponentId")] public virtual Team NextOpponent { get; set; }
 
    // Each Team also has a required Manager and Administrator, both of which are people
    public int ManagerId { get; set; }
    public int AdministratorId { get; set; }
    [ForeignKey("ManagerId")] public virtual Person Manager { get; set; }
    [ForeignKey("AdministratorId")] public virtual Person Administrator { get; set; }
}

The [ForeignKey] attributes are there for EF’s benefit, so it understands what we’re doing. If you’re using another data access technology, you may not need them, or you may need something else. MvcScaffolding doesn’t know or care about those them.

Of course, you don’t have to follow these conventions if you don’t want, but these are the ways that MvcScaffolding knows how to generate typical CRUD UI respecting the associations.

What else is new

There are a lot of other smaller improvements in MvcScaffolding 0.9.4. For example,

  • Based on your feedback, controller names are now pluralized by default (e.g., you get PeopleController rather than PersonController for a model of type Person, unless you explicitly enter PersonController as the controller name when scaffolding)
  • There’s now a single CreateOrEdit partial shared by both the Create and Edit views
  • Support for master pages in ASPX views is better
  • It runs on NuGet 1.1 now
  • You no longer need to compile (or even save!) your code before scaffolding it. Because it now uses the VS CodeModel API, compilation is irrelevant. However, make sure your code is syntactically valid when you scaffold, otherwise you’ll get a big spew of errors.

In fact, there are loads of improvements so I won’t list them all – see the source code log if you want to know everything!

In the next post I’ll show how you can customise the T4 templates and possibly even how to create completely new scaffolders of your own.

Reporting issues and giving feedback

By now, MvcScaffolding has a lot of nontrivial functionality and when you’re first starting to use it, you’ll inevitably run into something that doesn’t do what you expected. Personally, I’m still kind of new to EF, so I usually fail to configure it property. Or I make a change and can’t work out why it’s not appearing, then remember I haven’t re-run the scaffolder yet.

By all means please post brief comments about the design or feature ideas here on this blog, but note that it’s not the ideal place for involved discussions. Also, apologies in advance for slow replies: I’ll be away for the next week, and won’t reply to anything in that time :)

MvcScaffolding: Standard Usage

This post is part of a series about the MvcScaffolding NuGet package:

  1. Introduction: Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package
  2. This post: Standard usage: Typical use cases and options
  3. One-to-Many Relationships
  4. Scaffolding Actions and Unit Tests
  5. Overriding the T4 templates
  6. Creating custom scaffolders
  7. Scaffolding custom collections of files

This post describes some of the basic functionality you get with the MvcScaffolding package as soon as you install it. First, though, let’s explain a few core concepts. Don’t worry, there aren’t too many strange new concepts…

If this is the first time you’ve heard about MvcScaffolding, check out this other introductory post first.

What is a scaffolder?

A scaffolder is something that does scaffolding :) . Typically it consists of a PowerShell script that holds its logic, and a set of T4 templates that define the output it can produce, though you don’t need to know about how they work unless you want to make your own.

To see a list of available scaffolders, issue this command in the Package Manager Console:

Get-Scaffolder

image

Hopefully, your screen will be a little wider and you’ll actually be able to read the descriptions! Anyway, as you can see, scaffolders can live in NuGet packages and they have unique names like MvcScaffolding.RazorView. You could have lots of different scaffolders that produce views (e.g., you already have MvcScaffolding.AspxView too), and identify them by their unique name. For example, you could choose to scaffold an ASPX view as follows:

Scaffold MvcScaffolding.AspxView Index Team

Here, “Team” is the name of my model class (see the previous post for the steps to set up the project). Your model class might be Product or Customer or whatever. You can enter a fully-qualified type name, or just the unqualified name, and the scaffolder will search your referenced projects to find it.

Scaffolders can accept their own set of parameters.  In PowerShell, named parameters are introduced using a dash (“-“) characters, so to see a list of available parameters, enter text as far as the dash and then press TAB:

image

Some of those are specific to the scaffolder; others are common PowerShell parameters. I’ll explain what the scaffolder-specific ones do later.

What are “default scaffolders”?

You don’t want to keep typing out those long scaffolder names every time you want to use them (even with the tab-completion). Maybe you always want to use MvcScaffolding.RazorView by default for all views. Well, that’s exactly what defaults do.

To see what scaffolders are configured as defaults, enter the following command:

Get-DefaultScaffolder

image

As shown in the screenshot, default names are short, generic identifiers like Controller or Repository or View. That’s what makes it possible to enter “Scaffold Controller …” or “Scaffold View …” and not have to enter the full scaffolder name.

Interesting aside: when you first installed MvcScaffolding, it inspected your project and picked a default “View” scaffolder based on which view engine you appear to be using.

Default names are mapped onto full scaffolder names by means of an XML configuration file. You don’t need to see or edit the configuration file, though, because you can read it using Get-DefaultScaffolder, and write it using Set-DefaultScaffolder.

For example, to say that you want to generate ASPX views by default, enter the following:

Set-DefaultScaffolder View MvcScaffolding.AspxView

Now if you re-run Get-DefaultScaffolder, you’ll see that the name View resolves to MvcScaffolding.AspxView. Also, if you enter “Get-Scaffolder View”, you’ll see it returns information about the MvcScaffolding.AspxView scaffolder.

image

Note that when scaffolders call each other internally (e.g., the MvcScaffolding.Controller scaffolder internally calls Scaffold Repository … and Scaffold View …), they do so using the default names, not the full names. That means if you’ve configured some other default for View, it will get used by the Controller scaffolder automatically.

These defaults are stored on a per-project basis (so you can have different defaults for different projects), but you can also define solution-wide defaults by passing the “-SolutionWide” flag to Set-DefaultScaffolder.

Using the built-in scaffolders

Here’s what you can do with MvcScaffolding (and its parent package, T4Scaffolding) automatically:

Scaffold Controller <controllerNameOrModelType>

This produces an ASP.NET MVC controller for CRUD operations with an EF-code-first data context and views for Create, Details, Delete, Edit, and Index. Options include:

  • -ControllerName : Specify the name of the controller you want. If you’ve entered something that looks like a controller name, e.g., ProductsController or ProductController, we’ll use that name and go looking for a model class called Products or Product. If you enter something that looks like a model type, e.g., Product, we’ll look for that model and create you a controller called ProductsController.
  • -ModelType : By default we try to infer this from the controller name, but if you want your controllers and models to have totally unrelated names, you can specify a particular model type using this parameter. We’ll find any model class defined in your project or another project it references, but not in any external assembly.
  • -Project : Specify which ASP.NET MVC project the output goes into (you could have multiple such projects in your solution – by default we use the one specified by the “Default project” dropdown at the top of the Package Manager Console).
  • -CodeLanguage : Specify either “cs” or “vb” if you want. By default we use the same code language as your project. Theoretically you could pass “fsharp” or any other string for this parameter, but it would only work if the scaffolder could find a matching template.
  • -DbContextType : Specify the name of the database context class that should be generated or updated. By default, we use the name <yourProjectName>Context, e.g., SoccerSiteContext.
  • -Repository : This is a switch parameter, which means it doesn’t take any value. Just adding –Repository to the command line means that we’ll generate a repository class and interface, and the controller will do data access using that repository interface.
  • -Area : If you want the generated files to go into a specific ASP.NET MVC area, enter its name here. Note that you must have created that area already; the scaffolder doesn’t create areas automatically (yet).
  • -Layout : (Note: –MasterPage is a PowerShell alias for this parameter, so you can enter either name) If you want to use a specific Razor layout or ASPX Master Page, enter its virtual path here, e.g., “-Layout /Views/Shared/_SomeLayout.cshtml”. Otherwise, if you’re using Razor we’ll assume you want the default layout, and if you’re using ASPX we’ll look for a default Master Page (~/Views/Shared/Site.Master) or if not found produce a full HTML page (i.e., no master page).
  • -Force : By default, we don’t overwrite any files that already exist. If you do want to overwrite things, pass this switch.
  • -NoChildItems : If for some reason you only want to generate the controller class and don’t want any views, repositories, or data contexts, pass this switch.

In due course, we’ll add proper PowerShell-based documentation so you can get help on any specific scaffolder or parameter directly from the Package Manager Console.

Scaffold View <controllerName> <viewName>

This produces an empty view associated with the specified controller. Note that you should provide the short name for the controller, i.e., Products not ProductsController, as this is the name of the folder where the view goes. Also, you can specify:

  • -Template : Should be one of Create, Delete, Details, Edit, Index, or Edit. Instead of producing an empty view, we’ll use the specified template
  • -ModelType : Creates a strongly-typed view for the chosen model type. If you’re scaffolding a Create, Delete, Details, Edit, or Index view, the output will take account of the properties exposed by your model type.

Other parameters include: –Project, –Area, –Layout, –CodeLanguage, –Force. See above for information about these.

Scaffold Views <modelType>

This produces all of the standard CRUD views: Create, Delete, Details, Edit, and Index. Internally, the “controller” scaffolder calls this unless you’ve passed the –NoChildItems switch. It takes the same parameters as the “view” scaffolder.

Scaffold DbContext <modelType> <dbContextName>

This produces an Entity Framework Code First database context class for the given model type. If there’s already a database context class with matching name, we’ll simply add another DbSet<modelType>property to it without losing its existing properties. So, as you scaffold more models, your context will build up references to all the model types you’re persisting.

Other available parameters include:

  • -Folder : Forces the output to go into a specific folder relative to your project. By default, we use the /Models folder.
  • -Area : If you haven’t set a value for –Folder, this parameter populates –Folder using the ASP.NET MVC convention /Areas/<areaName>/Models.
  • Common ones such as –Project, –Force, and so on.
Scaffold Repository <modelType>

This produces a repository interface named after your model type (e.g., IProductRepository) along with an implementation that works using Entity Framework Code First. The repository exposes methods that get a specific model instance by primary key value, gets all model instances, adds a new model instance, and deletes a model instance. These operations don’t write to the database immediately – there’s also a “Save()” method which writes all the changes you made to the database.

Other parameters include:

  • -NoChildItems : Internally, the default repository scaffolder also calls “Scaffold DbContext …” to generate or update an underlying database context, which is what connects your application to the actual data access technology. If you don’t want to generate or update any database context, pass the –NoChildItems flag.
  • -Folder and –Area : These are passed on to the DbContext scaffolder (unless you pass the –NoChildItems flag, in which case the DbContext scaffolder won’t be called).
  • Common ones such as –Project, –Force, and so on.

Overriding the standard scaffolders with LINQ to SQL ones

To prove that this is an extensible system, I’ve created an experimental “LinqToSqlScaffolding” package that can replace the usual Entity Framework-powered “Repository” and “DbContext” scaffolders. To install it, enter the following into Package Manager Console:

Install-Package LinqToSqlScaffolding

Now if you run Get-Scaffolder, you’ll see there are two new ones:

image

If you want, you can invoke these directly (e.g., Scaffold LinqToSqlScaffolding.Repository <modelType>). They take roughly the same parameters as the standard EF repository and DbContext scaffolders.

But if you want to use LINQ to SQL by default, just update your default settings:

Set-DefaultScaffolder Repository LinqToSqlScaffolding.Repository

Now, whenever you call “Scaffold Repository” or even “Scaffold Controller”, it will generate code that works with LINQ to SQL. Note that to get this actually talking to a database successfully, you’ll need to:

  • Annotate your model classes with LINQ to SQL mapping attributes as described here, or provide a LINQ to SQL mapping file
  • Add a connection string called AppDb to your Web.config file, and ensure there’s really a database listening for connections, and set up the database schema to match your model.

Also, whenever you generate a controller for this, be sure to pass the –Repository switch because otherwise the controller will contain inline Entity Framework code.

Note that LINQ to SQL scaffolding support is basic, to say the least, and is primarily here to demonstrate how you can create a custom scaffolding package. In due course I hope others will create scaffolding packages to support other data access technologies, such as NHibernate. If you want the fame and glory and decide to be the one who builds that package for the community, let me know!

What’s next?

There’s still plenty more to cover about scaffolding. In the next post, I’ll describe how you can customise the T4 templates that define scaffolders’ output, and how you can create entirely new scaffolders of your own.

Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package

This post is part of a series about the MvcScaffolding NuGet package:

  1. This post: Scaffold your ASP.NET MVC 3 project with the MvcScaffolding package
  2. Standard usage: Typical use cases and options
  3. One-to-Many Relationships
  4. Scaffolding Actions and Unit Tests
  5. Overriding the T4 templates
  6. Creating custom scaffolders
  7. Scaffolding custom collections of files

Among many other improvements with ASP.NET MVC 3, we’re keen to make it easier to pick up and start using productively if you’re entirely new to the framework, and to automate common development tasks if you’re experienced and already know what you’re doing.

So, I’ve been working with Scott Hanselman lately on an enhanced new scaffolding package called MvcScaffolding. The term “Scaffolding” is used by many software technologies to mean “quickly generating a basic outline of your software that you can then edit and customise”. The scaffolding package we’re creating for ASP.NET MVC is greatly beneficial in several scenarios:

  • If you’re learning ASP.NET MVC for the first time, because it gives you a fast way to get some useful, working code, that you can then edit and adapt according to your needs. It saves you from the trauma of looking at a blank page and having no idea where to start!
  • If you know ASP.NET MVC well and are now exploring some new add-on technology such as an object-relational mapper, a view engine, a testing library, etc., because the creator of that technology may have also created a scaffolding package for it.
  • If your work involves repeatedly creating similar classes or files of some sort, because you can create custom scaffolders that output test fixtures, deployment scripts, or whatever else you need. Everyone on your team can use your custom scaffolders, too.

Other features in MvcScaffolding include:

  • Support for C# and VB projects
  • Support for the Razor and ASPX view engines
  • Supports scaffolding into ASP.NET MVC areas and using custom view layouts/masters
  • You can easily customize the output by editing T4 templates
  • You can add entirely new scaffolders using custom PowerShell logic and custom T4 templates. These (and any custom parameters you’ve given them) automatically appear in the console tab-completion list.
  • You can get NuGet packages containing additional scaffolders for different technologies (e.g., there’s a proof-of-concept one for LINQ to SQL now) and mix and match them together

It’s currently at a beta level so it is expected to work :) but if you push it in funny ways you might get odd results. Please let me know if you discover issues – I’m sure there’ll be some – so we can tidy it up and make it more robust.

Installation

The short version is this: Install-Package MvcScaffolding. If you understood that, do it and skip ahead to “Scaffolding a CRUD interface”. If not, read on.

1. Install ASP.NET MVC 3, which includes the excellent NuGet Package Manager.

2. Create or open an ASP.NET MVC 3 web application. I’m calling mine ‘SoccerSite’.

3. Install the MvcScaffolding package. You can install it using the NuGet Package Manager Console, so it only takes a few seconds and you don’t have to download anything using your browser.  To do so,

  • Open the Package Manager Console window using Visual Studio’s View->Other Windows->Package Manager Console menu item.
  • Enter the following:
Install-Package MvcScaffolding

image

  • That’s it! Note: be sure you installed MvcScaffolding, not MvcScaffold. We’ll retire the old MvcScaffold package shortly.

In case you’re wondering, EFCodeFirst is the new super-elegant version of Entity Framework that persists plain .NET objects to a relational database without any configuration fuss, T4Scaffolding is the core scaffolding infrastructure (locates types in your project, finds scaffolders in other packages, renders templates, etc), and MvcScaffolding is a set of ASP.NET MVC-specific templates (for controllers and views) that bolts onto the T4Scaffolding core.

Scaffolding a CRUD interface

Let’s create a model for a soccer team. Add the following class to your Models folder, then compile your solution (Ctrl-Shift-B):

namespace SoccerSite.Models
{
    public class Team
    {
        public int TeamId { get; set; }
        [Required] public string Name { get; set; }
        public string City { get; set; }
        public DateTime Founded { get; set; }
    }
}

Next, we can create a complete Create-Read-Update-Delete (CRUD) UI for this model by issuing a single scaffolding command into the Package Manager Console:

Scaffold Controller Team

Note: You can use the TAB key to autocomplete many things in the Package Manager Console. In this case, you can autocomplete the words “Scaffold” and “Controller”, since the scaffolding package knows about them. It doesn’t know about “Team”, though – we may add completion on model type names in a future version.

image

As you can see, it’s gone ahead and created a controller, a database context (a tiny bit of Entity Framework code that represents a data store), and views for all the CRUD actions. You can run it right now (Shift-F5), and as long as you have SQL Server Express running on your machine, EFCodeFirst will automatically connect to it, create your database schema, and you’ve got a basic working application without writing a single line of procedural code.

Note that since the model was called “Team”, the controller is called “TeamController”, so to reach it you need to point your browser to http://…/team:

image

The database is initially empty.

image

Creating an item. Validation rules are applied automatically. Note that since “Founded” is a DateTime it can’t be null and hence is required. Change it to DateTime? (i.e., with the question mark to make it nullable) if you want it to be optional.

image

Listing items

image

Deleting an item

But what if I don’t have SQL Express installed?

If you don’t have SQL Express installed and running, you may have got the following error when your code tried to read or write some data:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Blah blah blah…

No problem! You can quickly switch to use the new SQL Server Compact – a lightweight, in-process database – without having to download or install anything manually. Simply add SQL Server Compact to your project by issuing the following command in the Package Manager Console:

Install-Package EFCodeFirst.SqlServerCompact

Ta da – no more external database required. Run your project again (Shift-F5) and this time it will create and connect to a file-based database (a .sdf file will appear in your ~/App_Data folder). The EFCodeFirst.SqlServerCompact package adds a file to your project called AppStart_SQLCEEntityFramework.cs, which configures the runtime to use SQL CE.

Of course you probably still want the proper version of SQL Server when you eventually deploy your application for public use, but for small applications or for learning, SQL CE is really handy.

Scaffolding a repository

If you check out the code right now, you’ll see that TeamController reads and writes the data in SoccerSiteContext directly. That’s fine in many simple scenarios, but if you want to decouple your controller logic from persistence logic a little (e.g., so that you can write clean unit tests for the controller), you may prefer to reach your data through an interface.

No problem! Let’s regenerate the controller with the –Repository flag:

Scaffold Controller Team –Repository -Force

Notice that we also need to say –Force, otherwise the scaffolder won’t overwrite the files you already have in your project. Now the scaffolder will produce an additional class, TeamRepository, and the following interface which TeamRepository implements:

    public interface ITeamRepository
    {
        void Add(Team post);
        void Delete(int id);
        IEnumerable<team> GetAllTeams();
        Team GetById(int id);
        void Save();
    }

TeamController will now only read and write data using ITeamRepository. If you’re new to ASP.NET MVC it may not be obvious why this is desirable, but if you start trying to write unit tests or switch data access technologies, you’ll find this interface-based data access method to be much cleaner and more flexible.

There’s so much more

It’s not just about CRUD! You can use scaffolding to create any type of project item if you write a template for it. This blog post has covered only the absolute beginning of what you can do, so over the coming days I’ll write blog posts to cover:

  • Scaffolding specific individual items (e.g., views, repositories, etc) rather than whole controllers and related files
  • Getting additional scaffolder packages and controlling which ones are used by default. For example, there’s currently a proof-of-concept LINQ to SQL scaffolding package that you can install and set to act as the default type of repository/data context.
  • Customising the T4 templates that the scaffolders use to generate code
  • Creating entirely new custom scaffolders for new types of things (e.g., unit test fixtures)