2017-09-10 2 views
1

Je suis en train de créer une relation plusieurs à plusieurs en utilisant EFCore sur la même classe d'utilisateur que je basé sur EntityFrameworkCore.IdentityUser en suivant les instructions décrites here, here et here. J'ai la classe utilisateur suivant:plusieurs à plusieurs sur la même classe ne fonctionne pas

public class MyApplicationUser : IdentityUser 
{ 
    public virtual ICollection<MyApplicationUserJunction> MyApplicationUsers { get; set; } 
    public virtual ICollection<MyApplicationUserJunction> ManagingMyApplicationUsers { get; set; } 
} 

Voici ma table rejoindre:

public class MyApplicationUserJunction 
{ 
    public int MyApplicationUserId { get; set; } 
    public virtual MyApplicationUser MyApplicationUser { get; set; } 
    public int ManagedMyApplicationUserId { get; set; } 
    public virtual MyApplicationUser ManagedMyApplicationUser { get; set; } 
} 

Voici mon OnModelConfiguring:

protected override void OnModelCreating(ModelBuilder builder) 
{ 
    base.OnModelCreating(builder); 

    builder.Entity<MyApplicationUserJunction>() 
     .HasKey(uj => new { uj.ManagedMyApplicationUserId, uj.MyApplicationUserId}); 

    builder.Entity<MyApplicationUserJunction>() 
     .HasOne(uj => uj.MyApplicationUser) 
     .WithMany(qu => qu.MyApplicationUsers) 
     .HasForeignKey(uj => uj.MyApplicationUserId).OnDelete(DeleteBehavior.Restrict); 

    builder.Entity<MyApplicationUserJunction>() 
     .HasOne(uj => uj.ManagedMyApplicationUser) 
     .WithMany(qu => qu.ManagingMyApplicationUsers) 
     .HasForeignKey(uj => uj.ManagedMyApplicationUserId); 
} 

Chaque fois que je lance les outils EFCore ajoutent commande migrations, je obtenez l'erreur suivante:

The relationship from 'MyApplicationUserJunction.MyApplicationUser' to 'MyApplicationUser.MyApplicationUsers' with foreign key properties {'MyApplicationUserId' : int} cannot target the primary key {'Id' : string} because it is not compatible. Configure a principal key or a set of compatible foreign key properties for this relationship.

J'utilise le paquet EntityFrameworkCore.Tools.DotNet 1.0.0-preview3-final.

J'ai essayé d'utiliser une seule propriété de navigation sur la classe User, et j'ai essayé de ne pas spécifier la fonction WithMany comme décrit here mais sans succès.

+1

Lire la documentation pour [IdentityUser.Id] (https://msdn.microsoft.com/library/microsoft.aspnet.identity.entityframework.identityuser.id (v = vs.111) .aspx) et jetez un oeil au type. La propriété de clé étrangère doit être du même type –

+0

Merci! Je vais regarder en utilisant int comme clé primaire dans UserIdentity. – majjam

+0

Avez-vous réussi à le faire fonctionner? Si oui, veuillez répondre à la question pour partager les connaissances. –

Répondre

1

Pour obtenir ce travail avec EF de base 1, après la suggestion de Sir Rufo ci-dessus j'ai spécifié le type de TKey:

public class MyApplicationUser : IdentityUser<int> 
{ 
    public virtual ICollection<MyApplicationUserJunction> MyApplicationUsers { get; set; } 
    public virtual ICollection<MyApplicationUserJunction> ManagingMyApplicationUsers { get; set; } 
} 

et dans le contexte:

public class MyApplicationContext : IdentityDbContext<MyApplicationUser, IdentityRole<int>, int> 
{ 
    ... 

et dans la section AddIdentity dans ConfigureServices qui utilise également le IdentityRole générique:

services.AddIdentity<MyApplicationUser, IdentityRole<int>>(config => 
     { 
      config.User.RequireUniqueEmail = true; 
      config.Password.RequiredLength = 8; 
      config.Cookies.ApplicationCookie.LoginPath = "/Auth/Login"; 
     }) 
     .AddEntityFrameworkStores<MyApplicationContext, int>(); 

puis de mettre à jour d ceci à EF Core 2 qui nécessite d'autres modifications pour que l'Identité fonctionne. Comme cela est décrit par pealmeid here vous devez tirer de la IdentityRole:

public class MyRole : IdentityRole<int> 
{ 
    public MyRole() : base() 
    { 
    } 

    public MyRole(string roleName) 
    { 
     Name = roleName; 
    } 
} 

occasion à ConfigureServices:

public void ConfigureServices(IServiceCollection services) 
     { 
      services.AddIdentity<MyApplicationUser, MyRole>(config => 
      { 
       config.User.RequireUniqueEmail = true; 
       config.Password.RequiredLength = 8; 
      }).AddEntityFrameworkStores<MyApplicationContext>(); 
      ... 

j'utilise également l'authentification par cookie avant qui ne configuré plus dans la configuration de AddIdentity lambda, mais est à la place fait au niveau des services:

public void ConfigureServices(IServiceCollection services) 
    { 
     services.ConfigureApplicationCookie(options => options.LoginPath = "/Auth/Login"); 
     ... 

également un léger changement à la signature DbContext à utiliser le rôle dérivé t ype:

public class MyApplicationContext : IdentityDbContext<MyApplicationUser, MyRole, int> 
{ 
+0

Merci! En fait, c'est ce que j'attendais de voir, la deuxième propriété «ICollection». Je n'étais pas sûr que ce soit la bonne façon. –