2016-12-15 1 views
1

Je travaille avec EF Core 1.1 sur un projet de base mvc asp.net et je suis tombé sur, ce que je pense, une génération SQL non optimale. Mais bon, je ne suis pas un expert, donc je pourrais être mal :) completlyEntity Framework Core modèle un-à-un

modèles

public class Influencer 
{ 
    public int Id { get; set; } 

    public Instagram Instagram { get; set; } 

    public YouTube YouTube { get; set; } 

    // In the future, more social channels will be added so 
    // this is another concern I have how to architect/model properly 
} 

public class Instagram 
{ 
    public int Id { get; set;} 
    public string UserId { get; set; } 
    // More properties such as bio, image url, website and other stuff 
} 

public class YouTube 
{ 
    public int Id { get; set; } 
    public string ChannelId { get; set; } 
    // More properties such as bio, image url, statistics etc 
} 

Le UserId et ChannelId sont les « clés naturelles » (pardon mon abus du terme SQL correcte :) et les propriétés Id "clés artificielles" dans l'espoir de créer une interface/classe de base à simplement diverses opérations telles que supprimer, rafraîchir.

Donc à la question - comment configurer correctement cela dans le modelBuilder pour être correct?

SQL Je pense que devrait être le meilleur est quelque chose comme

Instagram 
- Id (PK) 
- UserId (AK) 
- InfluencerId (FK) 
YouTube 
- Id (PK) 
- ChannelId (AK) 
- InfluencerId (FK) 
Influencer 
- Id 

Cela devrait en effet contrainte une à une relation entre un influenceur et ses plates-formes sociales liées comme une contrainte bien que les parts de influenceur la Même plate-forme sociale (juste écrire cela me fait douter si je le veux vraiment car il peut y avoir des cas où un couple partage par exemple la même chaîne YouTube mais sont deux influenceurs individuels. plus tard)

Sur la modélisation actuelle

modelBuilder 
    .Entity<InstagramChannel>() 
    .HasAlternateKey(i => i.UserId) 
    .HasName("AK_UserId"); 

modelBuilder 
    .Entity<Profile>() 
    .HasOne<Instagram>() 
    .WithOne() 
    .HasForeignKey(typeof(Instagram), "ProfileId") 
    .HasConstraintName("FK_Instagram_Profile") 
    .OnDelete(DeleteBehavior.Cascade); 

Cela génère cependant une clé pour chacune des plates-formes sociales sur la Influencer tels que Influencer.InstagramId, Influencer.YouTubeId causant deux changements à la base de données quand une plate-forme sociale est supprimée.

Modifier marquage Ainsi, les propriétés Instagram, YouTube ne pas cartographiés produit SQL que je cherchais. Mais maintenant je ne sais pas si j'ai raté quelque chose - peut-être que certaines optimisations sont activées par EF core si la "table parente" a une relation directe avec ses tables liées. Peut-être cela rend-il juste impossible pour EF d'évaluer l'instruction Include(i => i.Instagram) car il veut probablement le faire sans le besoin d'une jointure.

Donc, un poste assez long et peut-être pas vraiment une question (enfin, je l'ai dit :) et probablement pas adapté dans ce forum. Mais bon, il y a beaucoup de gars et de filles qui pourraient ne pas partager leurs connaissances!

Merci

Répondre

1

Vous pouvez atteindre votre objectif sans utiliser modelBuilder, en utilisant les attributs:

public class Influencer 
{ 
    public int Id { get; set; } 

    [InverseProperty("Influencer")] 
    public Instagram Instagram { get; set; } 

    [InverseProperty("Influencer")] 
    public YouTube YouTube { get; set; } 
} 

public class Instagram 
{ 
    public int Id { get; set;} 
    public string UserId { get; set; } 

    public int InfluencerId { get; set; } 

    [ForeignKey("InfluencerId")] 
    public virtual Influencer Influencer { get; set; } 
} 

public class YouTube 
{ 
    public int Id { get; set; } 
    public string ChannelId { get; set; } 

    public int InfluencerId { get; set; } 

    [ForeignKey("InfluencerId")] 
    public virtual Influencer Influencer { get; set; } 
} 

Vous pouvez retirer InfluencerId propriétés si vous ne les aimez pas (je préfère avoir à champ explicite Id pouvoir y affecter une valeur int plutôt que d'assigner Influencer instances et de les lire à partir de DB uniquement pour cela).

En outre, vous pouvez supprimer virtual mots-clés, car EF de base (actuellement) ne les oblige (mais il ne supporte pas LazyLoading encore, donc je préfère garder « virtuelle » dans le cas où il sera nécessaire plus tard)

+0

Merci!Je vais l'essayer et il semble propre - moins verbeux que la syntaxe du générateur de modèle. Est-il possible d'ajouter une contrainte unique en utilisant des annotations de données? – joacar

+0

Non, actuellement EF Core ne supporte pas l'attribut 'Index' (mais il y a un [problème] (https://github.com/aspnet/EntityFramework/issues/4050) sur github à propos de son ajout) – Dmitry