Archives

Configuring Code First migrations for early success

These steps assume you have started with an MVC 4 new project, and that you’re just getting started with MVC/EF. Using automatic migrations is really useful for early development/demos, but when you start to get into ‘professional mode’, read this lovely blog post.

Step 1 Enable migrations

In the nuget package manager console type

enable-migrations -EnableAutomaticMigrations

Step 2 Enable automatic application of migrations

In your application start (or other preferred initialization location). Enter the following code (Replace UsersContext with your database context). Database originates from the System.Data.Entity namespace, and Configuration is from your newly added Migrations namespace.

Database.SetInitializer(new MigrateDatabaseToLatestVersion<UsersContext, Configuration>());

Step 3 Enable automatic drop

In Configuration.cs add this code to the constructor.

AutomaticMigrationDataLossAllowed = true;

 

What does all this do/help with?
The default project does not have migrations automatically enabled. And the error message you receive (if you start querying LINQ objects on your database context) if you don’t will be as follows:
InvalidOperationException
The model backing the 'UsersContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).

Enabling migrations sets up the whole migration system. But to enable automatic migrations you have to include -EnableAutomaticMigrations which simply adds the line AutomaticMigrationsEnabled = true; into the newly generated Configurations.cs file.

In conjunction with the database initializer,  development turnaround is more streamlined because you no longer have to type add-migration and update-database every time you make a change. That will happen automatically now. However, that’s not enough, if you want column removals you have to also perform step 3, where automatic data loss is supported.

When you are ready to release software (internally or externally) where you need strict version control and to upgrade databases on site, you should  remove automatic migrations and add a manual migration point.

NotSupportedException: The specified type member ‘blah’ is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

This one is easy to fix, you’re missing {get;set;}

// member does not have getter/setter
// - it needs to be a property
public class Item
{
   public int Id { get; set; }
   public string name; 
   // In the above, just add {get;set;} to name
}

ASP.NET configuration tool in Visual Studio 2012 – error message on a new MVC project.

If you’ve just launched PROJECT->ASP.NET CONFIGURATION tool from Visual Studio 2012, and experienced this error

System.ArgumentException: The parameter ‘PhysicalDirectory’ is invalid. Parameter name: PhysicalDirectory at System.Web.Configuration.VirtualDirectoryMapping.set_PhysicalDirectory(String value) at System.Web.Configuration.VirtualDirectoryMapping..ctor(String physicalDirectory, Boolean isAppRoot) at System.Web.Administration.WebAdminPage.OpenWebConfiguration(String path, String appPhysPath, Boolean getWebConfigForSubDir) at System.Web.Administration.WebAdminPage.OpenWebConfiguration(String path, Boolean getWebConfigForSubDir) at System.Web.Administration.WebAdminPage.VerifyAppValid()

You may have a special character in your filenames. In my stituation, I had an ampersand. Move your folder and try again.

On another note – this tool just doesn’t work with MVC 4 apps created with VS2012 out of the box. See here.

What does .mdf file contain in an asp.net project?

(For Visual Studio 2012, ASP.NET 4) The .MDF file in an ASP.NET project is quite simply a SQL Server 2012 database file which supports the MVC application. The Model classes define the structure of the database using the Code First methodology. By default, in Visual Studio 2012 when you create an MVC application it will use the LocalDB engine to access the database, in earlier versions of Visual Studio the SQL Server Express engine was used. Once generated you can view the structure of the database within visual studio, or attach the .mdf file to a SQL Server instance and view it with SQL Server Management Studio.
See the official asp.net site for some fantastic tutorials and videos.

Error message: ModelValidationException System.Data.Entity.EdmEntityType: EntityType ‘blah’ has no key defined. Define the key for this EntityType

You may see this error message when adding a controller.

You may see this error message via the debug output, or like this when adding a controller.

There are some simple fixes you can apply when this message occurs.

 // reason 1 - You've forgotten to include a key. All EF models need a key
 public class Item
 {
     public string name { get; set; }
     // just uncomment the line below
     // public int Id {get;set;}
 }
// reason 2 - Class name is not equal to Id member name
public class ItemClass
{
   public int ItemId {get;set;}
   // just change ItemId to Id, or change ItemClass to Item
}
// reason 3 - member does not have getter/setter - it needs to be a property
// If this isn't the Key, you may see a NotSupportedException instead:
//    The specified type member '<name>' is not supported in LINQ to Entities. 
//    Only initializers, entity members, and entity navigation properties are supported.
public class Item
{
   public int ItemId;
   // In the above, just add {get;set;}
}
// reason 4 the Id member is not public
public class Item
{
   // your member must be public
   protected int Id;
}
 // reason 5 - you're confusing Entity Framework
 public class Item
 {
     public int anId { get; set; }
     public int anotherId { get; set; }
 }

 // Just add [Key] to give EF a hint.
 // don't forget-  using System.ComponentModel.DataAnnotations;
 public class Item
 {
     [Key] 
     public int anId { get; set; }
     public int anotherId { get; set; }
 }

As you can see you don’t need the [Key] attribute and many automatic features like cascading delete operations are provided without having to provide attributes and data annotations or the fluent API. See the  conventions for code first development for more information.

Reason 6

A kind reader, Dmitry, below discovered another very odd incarnation of this error and shared it with us.

When creating a new controller with the Visual Studio UI, he accidentally chose his database context class in the edit box where he was supposed to specify his model class.

So EF was complaining that his ProductCtx didn’t have the key! Thanks Dimitry!

 

Reason 7

Another kind reader – Steven Bolens – provided this tidbit for reason 7.

 // reason 7 - you include a [required] property in the entity which is not 
 // natively supported by the Entity Framework
 public class Item
 {
     [Key]
     public int Id { get; set; }
     [Required]
     public Version ItemVersion { get; set; }         
 }

If you omit the Required attribute for the Version (System.Version) the EF simply silently ignores this ItemVersion property when generating the database. But when the property is Required then the EF tries to create a DbSet which is not possible because Version doesn’t have a key. The errormessage I get doesn’t specify that System.Version doesn’t have a key but instead it mentions a Versions class in my model namespace (which doesn’t exist).

Replacing the Version type with a string type (and converting the value to and from string) solves the problem. – Maybe there’s a cunning way around this with attribute decoration or derivation? – Giles

 

Reason 8

An anonymous contributor discovered this problem can also occur if you create the model before you install Entity Framework, even if you have done all the above steps. So make sure you install Entity Framework the first thing you do after you have created your project.

 

Allowing remote access to your IIS Express service

While developing an ASP.NET application with the IISExpress service, you might like to see how it looks on your mobile device connected to your LAN via Wi-Fi, or just any computer connected to your network.

If you do not happen to have the full IIS installed already, you can allow your IISExpress service to serve remote pages quickly and easily by following these steps.

Warning: By following these instructions you are solely liable for any security breach or problems you may face. Do not use this information if you do not agree with that statement.

Assume your machine name is ‘jedi’, and your port number is ‘16253’, replace appropriately.

1. Run a command prompt as administrator, and type in

netsh http add urlacl url=http://jedi:16253/ user=everyone

2. Open up the following file in Notepad or Visual Studio

MyDocuments\IISExpress\config\applicationhost.config

change the binding from:

<binding protocol="http" bindingInformation="*:16253:localhost" />

to:

<binding protocol="http" bindingInformation="*:16253:jedi" />

3. Restart the IISExpress service (use the tray icon or task manager, or a command prompt, type issreset).

4. In Visual Studio, change your Project->Properties->Web settings to launch http://jedi:16253 instead of http://localhost:16253

5. In a web browser on your development machine type http://jedi:16253/

6. Assuming all is good – Open up the port on the firewall.

        • Goto the Windows Firewall with Advanced Security panel
        • Create a new inbound rule
        • Click ‘Port’
        • Click ‘Next’
        • Click TCP
        • Enter a specific port 16253
        • Click ‘Next’
        • Click ‘Allow the connection’
        • Click ‘Next’
        • Click ‘Next’ (you could untick Public)
        • Give it a name “My MVC App” and press Finish.

7. You should now be able to access the page on the mobile device when connected to the Wi-Fi using http://jedi:16253/

For more advanced information see Scott Hansleman’s blog post. Also read some of the comments below where others have found problems and solutions.