3

Je suis ce tutoriel pour mettre en œuvre mon système d'amitié avec EF Core 1.1: http://www.codedodle.com/2014/12/social-network-friends-database.htmlComment mettre en œuvre une auto-référence de plusieurs à plusieurs relation avec Entity Framework Core 1.1?

Friendship.cs

public class Friendship 
{ 
    public Guid ApplicationUserId { get; set; } 
    public ApplicationUser ApplicationUser { get; set; } 

    public Guid FriendId { get; set; } 
    public ApplicationUser Friend { get; set; } 

    public StatusCode Status { get; set; } 

    public Guid ActionUserId { get; set; } 
    public ApplicationUser ActionUser { get; set; } 

    public byte[] Timestamp { get; set; } 
} 

public enum StatusCode 
{ 
    Pending = 0, 
    Accepted = 1, 
    Declined = 2, 
    Blocked = 3 
} 

ApplicationUser.cs

public class ApplicationUser : IdentityUser<Guid> 
{ 
    ... 

    public ICollection<Friendship> FriendRequestsMade { get; set; } 

    public ICollection<Friendship> FriendRequestsAccepted { get; set; } 

    public byte[] Timestamp { get; set; } 
} 

MyDbContext. cs

public class SocialCircleContext : IdentityDbContext<ApplicationUser, Role, Guid> 
{ 

    builder.Entity<Friendship>() 
     .HasIndex(x => new { x.ApplicationUserId, x.FriendId }) 
     .IsUnique(); 

    builder.Entity<Friendship>() 
     .HasOne(x => x.ApplicationUser) 
     .WithMany(y => y.FriendRequestsMade) 
     .HasForeignKey(x => x.ApplicationUserId).OnDelete(DeleteBehavior.Restrict); 

    builder.Entity<Friendship>() 
     .HasOne(x => x.Friend) 
     .WithMany(y => y.FriendRequestsAccepted) 
     .HasForeignKey(x => x.FriendId);   
} 

Résultat de la migration Add-InitialMigration

Impossible de déterminer la relation représentée par la navigation 'Friendship.ActionUser' de type 'ApplicationUser'. Configurez manuellement la relation ou ignorez cette propriété à partir du modèle.

De plus, comme EF Core évolue rapidement, j'ai trouvé plusieurs façons de le faire. Je ne suis pas sûr de ma mise en œuvre de la relation de plusieurs-à-plusieurs auto-référence, quelqu'un peut-il me donner un conseil?

  1. Comment puis-je définir la relation entre Friendship.ActionUser et ApplicationUser?
  2. Un conseil sur la façon correcte d'implémenter cette relation plusieurs-à-plusieurs auto-référencée? EF Core se déplace rapidement, j'ai trouvé de nombreuses façons en ligne, mais ils semblent désuets

Merci! :)

+0

Partiellement un bug ainsi classé https://github.com/aspnet/EntityFramework/issues/8886 – Smit

Répondre

1

Idéalement, une fois l'ambiguïté dans la découverte de la relation résolue, EF devrait créer le reste de la relation par convention, mais cela ne se produit pas en raison d'un bug. (Classé Bug)

Vos classes de modèle sont correctes pour ce que vous essayez de faire. Pour que EF crée le modèle avec succès, il y a peu de pièces manquantes à remplir.

D'abord, permet de résoudre l'exception que vous voyez. Votre classe ApplicationUser dispose de 2 collections de navigation pointant vers Friendship. Et Friendship classe a 3 navigation de référence pointant ApplicationUser. Alors que EF Core fait un bon travail pour créer des relations par convention, dans ce cas, il ne sait pas comment créer les paires de navigation navigation-inverse. La saisie de l'utilisateur est donc nécessaire via les annotations/API fluide. Dans votre cas, vous créez 2 relations en utilisant l'API fluide qui utilise 2 navigations de chaque côté. Cela nous laisse avec seulement la navigation Friendship.ActionUser sans aucune relation. À ce stade, EF Core n'a aucune confusion sur la façon de créer une relation à partir de lui, mais en raison du bug, il ne le fait pas. Cela signifie que vous devez configurer cette relation manuellement en utilisant l'API fluide.

builder.Entity<Friendship>().HasOne(e => e.ActionUser).WithOne().HasForeignKey<Friendship>(e => e.ActionUserId); 

Cela créerait une relation bi-univoque. Vous pouvez utiliser HasOne(...).WithMany() pour créer une relation un-à-plusieurs.

Ceci vous aiderait à dépasser l'erreur ci-dessus.Maintenant, vous verrez une autre erreur puisque la clé primaire n'a pas de clé primaire définie Friendship. Alors que l'article dit pour créer un index unique, mais pour la table de jointure many-to-many, la table de jointure est configurée avec un PK composite afin qu'il puisse représenter une connexion unique. Donc, au lieu d'appeler HasIndex comme ci-dessus, vous devez utiliser le code suivant.

builder.Entity<Friendship>().HasKey(e => new { e.ApplicationUserId, e.FriendId }); 

Après le code ci-dessus, vous pouvez supprimer HasIndex appel parce que PK sont toujours uniques et la plupart des bases de données ont l'index défini pour PK.

Avec les modifications ci-dessus, votre modèle devrait pouvoir fonctionner. Autre chose: Étant donné que la relation définie par Friendship.ActionUser est quelque peu ambiguë pour qu'elle soit un à un ou un-à-plusieurs, peut-être que cela ne devrait pas être une relation du tout. ActionUserId doit prendre l'une des valeurs ApplicationUserId ou FriendId, vous pouvez facilement accéder à l'ActionUser en choisissant l'une de ces navigations. Vous pouvez soit faire ActionUser [NotMapped] dans EF et calculé avec la valeur renvoyée ApplicationUser/Friend basée sur ActionUserId. Bien que ce sont des choix de conception. Il n'y a pas de bonne ou de mauvaise façon. Celui qui a le plus de sens et vous aide le plus dans la façon dont vous consommez devrait être utilisé.