26

Hi I'm planning to test EF Code First in one of my project. This is what I want actually. I have three tables and the structure is as follows

public partial class App_user
    {
        public int id { get; set; }
        public string name { get; set; }
        public string email_address { get; set; }
        public string password { get; set; }
        public int user_type { get; set; }
        public List<Role> Roles { get; set; }
    }

public partial class Role
    {
        public int id { get; set; }
        public string name { get; set; }
    }
public partial class User_role
    {
        public int user_id { get; set; }
        public int role_id { get; set; }
        public virtual Role Role { get; set; }
        public virtual App_user App_user { get; set; }
    }

In the third table there is no primary key. So it gives an error while running. Here is the error message -

System.Data.Edm.EdmEntityType: : EntityType 'User_role' has no key defined. Define the key for this EntityType. System.Data.Edm.EdmEntitySet: EntityType: The EntitySet User_roles is based on type User_role that has no keys defined.

Why its is happening? Is there a solution for this?

4 Answers 4

37

If think you are trying to model many-to-many relation between user and role. In such case your model is completely wrong.

Use this instead:

public partial class App_user
{
    public int id { get; set; }
    public string name { get; set; }
    public string email_address { get; set; }
    public string password { get; set; }
    public int user_type { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}

public partial class Role
{
    public int id { get; set; }
    public string name { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

This will create many-to-many automatically and you will not need to bother with junction table. If you need to expose junction table you must use this:

public partial class App_user
{
    public int id { get; set; }
    public string name { get; set; }
    public string email_address { get; set; }
    public string password { get; set; }
    public int user_type { get; set; }
    public virtual ICollection<User_Role> UserRoles { get; set; }
}

public partial class Role
{
    public int id { get; set; }
    public string name { get; set; }
    public virtual ICollection<User_Role> UserRoles { get; set; }
}

public partial class User_role
{
    [Key, ForeignKey("App_user"), Column(Order = 0)]
    public int user_id { get; set; }
    [Key, ForeignKey("Role"), Column(Order = 1)]
    public int role_id { get; set; }
    public virtual Role Role { get; set; }
    public virtual App_user App_user { get; set; }
}

Exposing junction table is meaningless if you don't need additional properties in it.

To your error - each entity in Entity framework must have primary key defined.

Sign up to request clarification or add additional context in comments.

5 Comments

[Key, ForeignKey("App_user"), Column(Order = 0)] - What is the namespace to use with it?
System.ComponentModel.DataAnnotations (it has also separate assembly).
@LadislavMrnka, I do not seem to apply [Key, ForeignKey("App_user"), Column(Order = 0)], only [Key] is available, what am I missing ? Thanks.
@autrevo: Make sure you are referencing EntityFramework.dll. .NET 4.0 does not contain those annotations directly (.NET 4.5 does).
the ForeignKey("") is not really necessary.
19

You can simply do like this:

public partial class User_role
{
    [Key]
    public int user_id { get; set; }
    [Key]
    public int role_id { get; set; }
    public virtual Role Role { get; set; }
    public virtual App_user App_user { get; set; }
}

4 Comments

wouldn't that make user_id key? What if user is in many roles?
what about something like that?
@YngveB.Nilsen how do you add the [Key] Property ? I refered System.ComponentModel.DataAnnotation. But it only shows [foreignkey] is [key] under a diferent directory ?
@omachu23 back in 2011 (when this answer was written) it was in System.ComponentModel.DataAnnotation, but what it is today is a different question :)
1

Because I used an ADO.net Entiry Data Model with automated generated code I didn't want to change the Model classes so I changed the WebApiConfig.cs to define the keys of the underlying models:

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
EntitySetConfiguration<Registration> EntitySetConfiguration_Registration = builder.EntitySet<Registration>("Registration");
EntitySetConfiguration<Lead> EntitySetConfiguration_Lead = builder.EntitySet<Lead>("Lead");
EntitySetConfiguration<Session> EntitySetConfiguration_Session = builder.EntitySet<Session>("Session");
EntitySetConfiguration_Registration.EntityType.HasKey(p => p.Registration_Id);
EntitySetConfiguration_Lead.EntityType.HasKey(p => p.Lead_Id);
EntitySetConfiguration_Session.EntityType.HasKey(p => p.Session_Id);
config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel());

Comments

0

make sure you are using (using System.ComponentModel.DataAnnotations;)

just add the keyword [Key] at the top of the data field in the Model

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.