0
votes

EF Core mauvaise déclaration de jointure

J'ai les classes de modèle suivantes dans EF Core 2.2

FROM Posts [p]   
LEFT JOIN Users [p.Users] ON [p].[UserId] = [p.Users].[Id]


3 commentaires

Quelle est la relation entre post et utilisateur?


Si vous voulez dire par ce Builder.hasone ("Modèles.post", "Post"). Frais ("Utilisateur"). Afferignkey ("modèles.user", "postide");


et pour l'utilisateur, il est Builder.hasone ("modèles.user"). Avec Manyy ("Posts"). Aforeignke y ("UserID")


3 Réponses :


1
votes

La relation entre l'utilisateur et la poste est fausse. Cela devrait être votre modèle:

public class User
{
    [Key]
    public long Id { get; set; }
    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    [Key]
    public long Id { get; set; }
    [ForeignKey("User")]
    public long UserId { get; set; }
    public virtual User User { get; set; }
}


7 commentaires

Cela n'inclut pas la dernière postide dans le modèle utilisateur. Comme je l'ai dit dans la question, j'ai besoin d'inclure la dernière postide dans le modèle utilisateur.


Pourquoi ferais-tu ça? C'est une dénormalisation inutile. Vous pouvez récupérer le dernier postide de la collection de messages.


Oui, c'est une certaine dénormalisation que je suis au courant. Juste pour un peu de performance boost


@Reza: un identifiant postal dans un utilisateur impliquerait qu'un utilisateur n'a que 1 poste, en tant qu'utilisateur n'aurait qu'une seule pièce d'identité. Bien que vous puissiez mapper EF pour faire référence à un seul poste aux côtés d'une collection de messages, il n'existe aucun moyen de faire respecter de manière fiable quels poster ce seul poste fait référence à (premier post? Dernier message?), Ou même si elle fait référence à un post de la collection de messages pour cet utilisateur. Ce n'est pas tellement une question de dénormalisation, mais de comprendre la relation souhaitée de vos données.


@Stevepy, donc dans une telle situation, je ne peux pas utiliser dbcontext.post.include (p => p.user) et doit les rejoindre manuellement en utilisant dbcontext.poss.join (... ) ? J'utilise actuellement rejoindre (...)


Vous pouvez certainement utiliser inclure (p => p.user) , car un message à avoir qu'un utilisateur n'exige pas qu'un utilisateur ait un poste singulier, seulement que la table postale a un ID utilisateur. Un utilisateur peut, ou peut ne pas avoir de collection de postes. Un utilisateur peut avoir de nombreux messages (0, 1, .. 100) Un poste nécessiterait un seul utilisateur. La poste peut référencer son utilisateur et un utilisateur peut éventuellement référence à ses messages. (Pluriel) en mettant un identifiant postal singulier dans votre utilisateur, vous confondez EF en pensant que la relation est de 1 à 1. Développez peut-être votre question pour décrire pourquoi vous souhaitez référencer 1 poste singulier d'un utilisateur.


@Stevepy, il ne s'agit pas d'un poste et d'un utilisateur, je suis confronté à ce problème pour un autre scénario. Dans mon scénario, j'ai n à n relation qui enregistre certaines modifications et une de ces modifications est attribuée à l'entité. Je peux mettre un drapeau actif et le basculer, mais ce serait bien s'il y avait un moyen de dire à EF que j'intervient à l'utilisateur de Post, puis ID utilisateur est la clé de jonction non du postide.



2
votes

Dans la discussion sur l'autre réponse, il semble que vous souhaitiez que un utilisateur contienne des messages, mais également à l'utilisateur de suivre une référence au dernier message. EF peut mapper cela, mais vous devrez probablement être un peu explicite sur les relations.

par exemple: p> xxx pré>

puis une configuration pour assurer la relation EF Entre utilisateurs et messages correctement: p> xxx pré>

Vous pouvez y accomplir dans l'événement OnModelCreat avec la référence ModelBuilder également. Notez ici, je ne déclare pas les propriétés FK dans mes entités. C'est une option, mais je ne recommande généralement pas de ne pas déclarer FKS d'éviter les problèmes de mise à jour de référence par rapport à FK. J'ai nommé la dernière fois que LitterPost FK comme LastPostid Juste pour révéler un peu plus précisément ce qu'il est pour. Il pourrait être mappé à un "postide" si vous le souhaitez. P>

permet maintenant de dire que je vais ajouter un nouveau post et que je souhaite l'associer à l'utilisateur et que vous l'attribuez comme le dernier utilisateur pour cet utilisateur : p> xxx pré>

Vous pouvez mettre à jour la référence "la plus récente" en chargement de l'utilisateur et en définissant la référence de la dernière référence à la poste souhaitée. P>

Il y a un risque Avec cette structure, cependant que vous devriez considérer. La question est qu'il n'ya aucun moyen d'appliquer de manière fiable (à un niveau de données) que la référence LitterPost dans un utilisateur référente réellement un poste associé à cet utilisateur. Par exemple, si j'ai un dernier message pointant vers un article en particulier, je supprime que la référence postale de la collection de messages de l'utilisateur peut aboutir à des erreurs de contrainte FK ou simplement dissocier le poste de l'utilisateur, mais le dernier poste de l'utilisateur encore points à cet enregistrement. Je peux également attribuer le message d'un autre utilisateur à la dernière référence de cet utilisateur. C'est-à-dire p> xxx pré>

et ce serait parfaitement bien. L'utilisateur 2 "LitterPostiD" de l'utilisateur serait défini sur ce nouveau poste, même si cet ordinateur de cet article fait référence uniquement à User1. P>

Une meilleure solution lorsqu'il s'agit de quelque chose comme un dernier message est de pas em > Dénormalisez le schéma pour l'adapter. Au lieu de cela, utilisez des propriétés malappées dans l'entité pour le dernier message ou mieux, comptez sur la projection pour récupérer ces données lorsqu'il est nécessaire. Dans les deux cas, vous supprimeriez le LARTPOSTID de la table utilisateur P>

Propriété non manquée: P>

var userAndPost = context.Users.Where(x => x.UserId == userId)
    .Select(x => new { User = x, LatestPost = x.Posts.OrderByDescending(PostedAt).FirstOrDefault()} ).Single();


0 commentaires

0
votes

Vous avez assez de réponses sur cette question sur la manière de créer le modèle, je vais simplement mettre en évidence ce qui ne va pas dans votre classe

Vous avez Craete postide dans le modèle utilisateur comme FK et il le considérera donc toujours comme une relation entre l'utilisateur et la poste, vous devez le supprimer et le concevoir quelque chose de similaire à ce qui est dit par Steve


0 commentaires