web-dev-qa-db-fra.com

Que dois-je ajouter à la fonction OnModelCreating (DbModelBuilder modelBuilder) pour définir les relations entre la personne et le rôle?

J'utilise EntityFramework version 5.0 dans le projet WinForms, .net 4.5.

J'ai créé 2 entités importantes pour moi

    public class Role
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Name { get; set; }
        public bool StockPermission { get; set; }
        public bool ItemPermission { get; set; }
        public bool OrderPermission { get; set; }
        public bool PersonPermission { get; set; }
        public bool StatisticPermission { get; set; }
    }

    public class Person
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public String Name { get; set; }
        public String Nickname { get; set; }
        public String Contact { get; set; }
        public System.DateTime Created { get; set; }
        public String Pincode { get; set; }

        public virtual ICollection<Role> Role { get; set; }
        public virtual Person Creator { get; set; }
    }

et classe dbContext:

    public class SusibarDbContext : DbContext
    {
        public DbSet<Entity.Role> Roles { get; set; }
        public DbSet<Entity.Person> Persons { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //base.OnModelCreating(modelBuilder);
        }
    }

s'il vous plaît, pouvez-vous m'aider ce que je dois ajouter à la fonction OnModelCreating(DbModelBuilder modelBuilder) pour définir les relations entre la personne et le rôle?

Une personne peut avoir plusieurs rôles (mais ne peut pas être nulle), différentes personnes peuvent avoir le même rôle.

Une personne peut avoir une personne "créatrice" (peut être nulle), différentes personnes peuvent avoir le même "créateur"

Si vous pouviez être si gentil, conseillez-moi simplement la solution :-(

15
eCorke

Si vous souhaitez utiliser l'API Fluent pour cela, regardez cette rubrique de MSDN. Vous devez utiliser la relation plusieurs-à-plusieurs et EF créera une table requise pour le cas où une personne peut avoir plusieurs rôles et un rôle avec plusieurs personnes. Quelque chose comme ça:

modelBuilder.Entity<Person>().HasMany(x => x.Roles).WithMany();

Vous pouvez également créer cette relation sans utiliser l'API Fluent. Vous devez créer la propriété de navigation ICollection<Person> Persons dans la classe Role et EF créeront également une table et une relation appropriées.

16
klappvisor

Quelque chose comme ça devrait faire l'affaire:

Créez un POCO appelé PersonRole. Ceci est destiné à modéliser la relation entre un Person et un Role.

public class PersonRole
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public Person Person { get; set; }
    public Role Role { get; set; }
}

Dans la classe Person, remplacez:

public virtual ICollection<Role> Role { get; set; }

avec:

public virtual ICollection<PersonRole> PersonRoles { get; set; }

Si vous le souhaitez, vous pouvez ajouter ce qui suit à la classe Role:

public virtual ICollection<PersonRole> PersonRoles { get; set; }

cela est facultatif, mais cela peut être utile si vous souhaitez regarder tous les People avec un Role particulier.

Dans la méthode OnModelCreating, utilisez ce code pour vous assurer qu'un PersonRole appliquera les propriétés Person et Role non nullables _.

modelBuilder.Entity<PersonRole>().HasRequired(p => p.Person);
modelBuilder.Entity<PersonRole>().HasRequired(p => p.Role);

Modifier:

La raison de la création du PersonRole POCO est de garantir qu'un Role peut être réutilisé entre différents utilisateurs. Utilisation de l'existant public virtual ICollection<Role> Role { get; set; } fonctionnera, mais il ne fonctionnera probablement pas comme prévu.

Avec la relation public virtual ICollection<Role> Role { get; set; }, ce que EF va faire est d'augmenter la table Role avec un champ supplémentaire, par exemple PersonId, qui sera utilisé pour relier un Person à son Roles. Le problème est clair: sans la table de liaison PersonRole, vous ne pourrez pas donner le même Role à deux personnes.

1
nick_w

Bien que ce ne soit pas une réponse directe à votre question, utilisez les conventions de dénomination EF pour éviter les annotations et garder vos classes d'entités propres. Je vais démontrer 2 situations:

n - plusieurs utilisant la convention de dénomination EF

Le rôle a plusieurs personnes, la personne a un rôle

n - plusieurs là où aucune convention de dénomination n'existe (parent-enfant du même type)

La personne en a créé plusieurs, la personne a un créateur)

public class Role
{
    public int RoleId { get; set; }
    public string Name { get; set; }
    ...

    public virtual ICollection<Person> Persons { get; set; }
}

public class Person
{
    public int PersonId { get; set; }
    public int CreatorId { get; set; } 
    public int RoleId { get; set; } 
    ...

    public virtual Role Role { get; set; }
    public virtual Person Creator { get; set; }
    public virtual ICollection<Person> Created { get; set; }
}

Pour la relation créée par le créateur dans OnModelCreating:

modelBuilder.Entity<Person>()
    .HasOptional(p => p.Creator)
    .WithMany(p => p.Created)
    .HasForeignKey(p => p.CreatorId);

Avec "ClassName" + "Id" (sensible à la casse), EF supposera qu'il s'agit automatiquement de la clé primaire/identificateur. La relation rôle-personne sera créée automatiquement en raison du mappage virtuel combiné avec la clé primaire "RoleId"

1
Talon