Use the ColumnAttribute or the HasKey method to specify an order for composite primary keys

It took a lot of fiddling about and testing different things. I was clueless until I decided to make a new vanilla project with the similar data structure from scratch. And when I installed EntityFramework from NuGet, I was shown a message:

Known Issues with Entity Framework 4.x and .NET Framework 4.5

Entity Framework 4.1 thru 4.3 included additional data annotations in the System.ComponentModel.DataAnnotations namespace in the EntityFramework assembly. In .NET 4.5 these annotations were moved to be part of the .NET Framework in the System.ComponentModel.DataAnnotations.Schema namespace of the System.ComponentModel.DataAnnotations.dll assembly. If you are using EF 4.x and targeting .NET 4.5 this results in two data annotations with the same name in different assemblies. Because the annotations in the .NET Framework are in a different namespace we were not able to use type forwarding to avoid this conflict.

It is possible to use EF 4.x on .NET 4.5 but we recommend using the latest pre-release version of EF 5. If you are not using the affected data annotations there is no impact on your code. If you are using the data annotations in a C# project you can use the extern modifier to ensure your code uses the annotations from EntityFramework.dll (http://msdn.microsoft.com/en-us/library/e59b22c5(v=VS.80).aspx). If you use the new annotations from the System.ComponentModel.DataAnnotations.dll assembly in .NET 4.5 they will not be processed by Code First.

The affected annotations are:

  • Column
  • ComplexType
  • DatabaseGenerated
  • DatabaseGeneratedOption
  • ForeignKey
  • InverseProperty
  • MaxLength
  • MinLength
  • NotMapped
  • Table

At that point I realised that my data project was freshly created in VS2012 and was by default targeting .Net 4.5 and the rest of my project in solutions were migrated from VS2010 and targeting .Net 4.0. So I have updated all the projects to target .Net 4.5 and got the pre-release of EntityFramework 5.0.

Make sure you update your projects first to Net4.5, after that do update EF to 5.0, otherwise it will hate you forever and many bunnies will die.

This screencast is a great starter for updating to EF5.0

At that point my error was gone, but I was getting different one. I could not add migration because it could not find Migration Configuration, even though I had configuration set up just seconds before it. That again took a lot of fiddling with NuGet, uninstalling ad re-installing packages. Then I saw in packages.config lines like this:

package id="EntityFramework" version="5.0.0-rc" targetFramework="net40" 

I have changed targetFrameworkto "net45" and now I'm getting the expected behavior from migrations. I guess there would be a better way to get nuget target .Net 4.5 with packages, but that's what worked for me.

I hope this will save somebody banging their head on a wall.


public class UserProjectRole
{
   [Key, Column (Order = 0)]
   public Guid UserProjectRoleID { get; set; }

   [Key, Column (Order = 1)]
   [ForeignKey("Project")]
   public Guid ProjectID { get; set; }

   [Required]
   public Project Project { get; set; }

   public Guid AppUserGuid { get; set; }

   // followed by a number of unrelated String fields.
}

public class Project: Base
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid ProjectID { get; set; }

    public virtual ICollection<UserProjectRole> UserRoles { get; set; }

    // followed by a number of unrelated String fields.

}

public class SiteContext : DbContext
{
    public DbSet<Project> Projects { get; set; }

    public DbSet<UserProjectRole> UserProjectRoles { get; set; }
}

Try this, especially with the [Required] above the public Project Project {get; set;}.

If this doesn't work, try it again and remove the [Key, Column (Order = 1)] above the [ForeignKey("ProjectID")]


Here is the fix for those with dead bunnies (having updated to EF 5.0 before updating to .Net 4.5):

In the csproj files, change

<Reference Include="EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\packages\EntityFramework.5.0.0\lib\net40\EntityFramework.dll</HintPath>
</Reference>

TO

<Reference Include="EntityFramework">
  <HintPath>..\packages\EntityFramework.5.0.0\lib\net45\EntityFramework.dll</HintPath>
</Reference>

Pretty obvious when you know it....