Entity Framework Code-First — определите ключ для этого EntityType

Привет, я планирую протестировать EF Code First в одном из моих проектов. Это то, чего я хочу на самом деле. У меня есть три таблицы, и структура выглядит следующим образом

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; }
    }

В третьей таблице нет первичного ключа. Поэтому выдает ошибку во время работы. Вот сообщение об ошибке -

System.Data.Edm.EdmEntityType: : EntityType 'User_role' не имеет определенного ключа. Определите ключ для этого EntityType. System.Data.Edm.EdmEntitySet: EntityType: EntitySet User_roles основан на типе User_role, для которого не определены ключи.

Почему это происходит? Есть ли решение для этого?


person Mukesh    schedule 30.03.2011    source источник


Ответы (4)


Если вы думаете, что пытаетесь смоделировать отношение «многие ко многим» между пользователем и ролью. В таком случае ваша модель совершенно неверна.

Используйте это вместо этого:

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; }
}

Это автоматически создаст многие ко многим, и вам не нужно будет возиться с соединительной таблицей. Если вам нужно открыть соединительную таблицу, вы должны использовать это:

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; }
}

Выставлять соединительную таблицу бессмысленно, если в ней не нужны дополнительные свойства.

К вашей ошибке - каждый объект в Entity framework должен иметь определенный первичный ключ.

person Ladislav Mrnka    schedule 30.03.2011
comment
[Key, ForeignKey (App_user), Column (Order = 0)] — какое пространство имен использовать с ним? - person Mukesh; 30.03.2011
comment
System.ComponentModel.DataAnnotations (также имеет отдельную сборку). - person Ladislav Mrnka; 30.03.2011
comment
@LadislavMrnka, кажется, я не применяю [Key, ForeignKey("App_user"), Column(Order = 0)], доступен только [Ключ], что мне не хватает? Спасибо. - person Abhijeet; 13.12.2012
comment
@autrevo: убедитесь, что вы ссылаетесь на EntityFramework.dll. .NET 4.0 не содержит этих аннотаций напрямую (в .NET 4.5 они есть). - person Ladislav Mrnka; 13.12.2012
comment
ForeignKey("") на самом деле не нужен. - person AceMark; 31.05.2015

Вы можете просто сделать так:

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; }
}
person Yngve B-Nilsen    schedule 30.03.2011
comment
разве это не сделало бы ключ user_id? Что делать, если пользователь находится во многих ролях? - person archil; 30.03.2011
comment
а как насчет такого? - person Yngve B-Nilsen; 30.03.2011
comment
@ YngveB.Nilsen, как добавить свойство [Key]? Я сослался на System.ComponentModel.DataAnnotation. Но это только показывает, что [внешний ключ] находится [ключ] в другом каталоге? - person CodeEngine; 11.05.2015
comment
@omachu23 еще в 2011 году (когда был написан этот ответ) он был в System.ComponentModel.DataAnnotation, но то, что сегодня, - это другой вопрос :) - person Yngve B-Nilsen; 15.05.2015

Поскольку я использовал Entiry Data Model ADO.net с автоматически сгенерированным кодом, я не хотел изменять классы Model, поэтому я изменил WebApiConfig.cs, чтобы определить ключи базовых моделей:

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());
person LiQuick.net    schedule 30.03.2014

убедитесь, что вы используете (используя System.ComponentModel.DataAnnotations;)

просто добавьте ключевое слово [Key] вверху поля данных в модели

person Nelson    schedule 23.05.2017