Question EF 4.1: Différence entre .WithMany () et .WithOptional ()?


Vous trouverez ci-dessous deux configurations API similaires:

Avec beaucoup()

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithMany()
            .WillCascadeOnDelete(false); 

WithOptional ()

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithOptional()
            .WillCascadeOnDelete(false);

Ce que j'essaie d'exprimer ici est: chaque Country nécessite un béton Currency, mais un Currency peut avoir zéro, un ou plusieurs pays assignés.

Lequel des énoncés ci-dessus devrais-je utiliser? Ou en d'autres termes: quelle est exactement la différence entre .WithMany() et .WithOptional() les opérateurs?


19
2018-03-24 15:38


origine


Réponses:


Si votre modèle ressemble à ceci:

public class Country
{
    public int CountryId { get; set; }
    public Currency Currency { get; set; }
}

public class Currency
{
    public int CurrencyId { get; set; }
}

puis ...

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithOptional()
            .WillCascadeOnDelete(false);

... crée une relation de clé étrangère dans la base de données où CountryId dans le Countries la table est la clé primaire et la clé étrangère à la CurrencyId du Currencies table en même temps, de sorte que le Countries table a une seule colonne  CountryId. UNE Currencies enregistrement peut vivre sans un lien Countries record. Mais si un Currencies enregistrement a un lien Countries enregistrer alors pas plus d'un parce que la clé étrangère est CountryId qui est la clé primaire en même temps et ne peut donc être que dans un seul enregistrement. Donc la relation Currencies -> Countries est 1-to-0...1.

L'autre exemple ...

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithMany()
            .WillCascadeOnDelete(false);

... crée une deuxième colonne  CurrencyId dans le Countries table de la base de données qui est non nullable et est une clé étrangère à la CurrencyId du Currencies table. Donc, ici, il est possible qu'un Currencies enregistrement n'a aucun lien Countries enregistrement ou un ou plusieurs, car la clé étrangère est maintenant une autre colonne, non identique à la clé primaire. Par conséquent, plus d'une ligne dans le Countries table peut avoir la même clé étrangère. La relation Currencies -> Countries Voici 1-to-0...n.

modifier

Si vous prenez le code suivant pour les deux modèles configurés différemment ...

Country country1 = new Country();
Country country2 = new Country();
Currency currency = new Currency();

country1.Currency = currency;
country2.Currency = currency;

context.Countries.Add(country1);
context.Countries.Add(country2);

context.SaveChanges();

... alors le second cas (.WithMany) fonctionne: nous obtenons deux nouveaux pays et une devise dans la base de données.

Cependant, un peu étrange est que dans le second cas (.HasOptional) seul le premier Pays est stocké, le second est simplement ignoré. En fait, je m'attendais à obtenir une exception. Je ne sais pas si cela doit être considéré comme un bug.

Edit2

Changer l'ordre dans l'exemple ci-dessus pour ...

context.Countries.Add(country1);
context.Countries.Add(country2);

country1.Currency = currency;
country2.Currency = currency;

... déclenche l'exception attendue dans le cas ".HasOptional".


31
2018-03-24 17:49