EntityType ‘Membership’ has no key defined. Define the key for this EntityType.


I have been using the Entity Framework since the very first version, and I’ve recently upgraded to version 5.2 on a rather large project of mine. Now, I’ve been using the ObjectContext all the time, since I have a lot of work invested in it, but I’m adding a new service to an existing app and for that I decided to use Code First and the DbContext instead. Well, it is not entire Code First, because I had the database in place and simply used the Reverse Engineer Code First option from the Entity Framework context menu (available when right-clicking the project in Solution Explorer in Visual Studio 2012).

I used my new and custom DbContext from a WCF data service, but when trying to access the service using Internet Explorer, I got the following error:

One or more validation errors were detected during model generation:
System.Data.Entity.Edm.EdmEntityType: : EntityType ‘Membership’ has no key defined. Define the key for this EntityType.
System.Data.Entity.Edm.EdmEntityType: : EntityType ‘Profile’ has no key defined. Define the key for this EntityType.
System.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet ‘Memberships’ is based on type ‘Membership’ that has no keys defined.
System.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet ‘Profiles’ is based on type ‘Profile’ that has no keys defined. ‘. See server logs for more details.

Now, as you may have guessed, I reverse engineered the tables used by the Universal Providers for the ASP.NET membership system. I need custom access to these tables, so I needed to get it working, and there are plenty of other developers who have come across these errors. However, none of the proposed solutions worked for me. The solution was rather simple, as I needed to decorate the UserId property with some attributes, as shown below. Yes, I like to use attributes and not the fluent Code First API…

public class Membership
{
     public System.Guid ApplicationId { get; set; }
     [Key]
     [ForeignKey("User")]
     public System.Guid UserId { get; set; }
     public string Password { get; set; }
     public int PasswordFormat { get; set; }
     public string PasswordSalt { get; set; }
     public string Email { get; set; }
     public string PasswordQuestion { get; set; }
     public string PasswordAnswer { get; set; }
     public bool IsApproved { get; set; }
     public bool IsLockedOut { get; set; }
     public System.DateTime CreateDate { get; set; }
     public System.DateTime LastLoginDate { get; set; }
     public System.DateTime LastPasswordChangedDate { get; set; }
     public System.DateTime LastLockoutDate { get; set; }
     public int FailedPasswordAttemptCount { get; set; }
     public System.DateTime FailedPasswordAttemptWindowStart { get; set; }
     public int FailedPasswordAnswerAttemptCount { get; set; }
     public System.DateTime FailedPasswordAnswerAttemptWindowsStart { get; set; }
     public string Comment { get; set; }
     public virtual Application Application { get; set; }
     public virtual User User { get; set; }
}

public class Profile
{
     [Key]
     [ForeignKey("User")]
     public System.Guid UserId { get; set; }
     public string PropertyNames { get; set; }
     public string PropertyValueStrings { get; set; }
     public byte[] PropertyValueBinary { get; set; }
     public System.DateTime LastUpdatedDate { get; set; }
     public virtual User User { get; set; }
}

It is needed to map the User navigation property with the User table by means of the UserId property. 🙂

Advertisements