Vous êtes peut-être victime des conventions de mappage EF Code-First qui créent automatiquement une relation entre NationAllies
et toNation
vous ne voulez pas avoir.
Si je vous comprends bien (mais je ne suis pas sûr à 100 %, si c'est le cas), vous voulez en fait avoir deux relations et vous n'avez exposé qu'une seule extrémité de la relation dans chacune des entités. Alors, NationAllies
ne pointe PAS vers toNation
mais à une nation Propriétaire "invisible" dans votre NationAlly
entité.
Si tel est le cas, vous devez écraser explicitement les mappages de convention. Dans l'API Fluent d'EF 4.1, cela pourrait ressembler à :
public class MyContext : DbContext
{
public DbSet<Nation> Nations { get; set; }
public DbSet<NationAlly> NationAllies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Nation>()
.HasMany(n => n.NationAllies)
.WithRequired()
.Map(conf => conf.MapKey("OwnerID"))
.WillCascadeOnDelete(false);
modelBuilder.Entity<NationAlly>()
.HasRequired(a => a.toNation)
.WithMany()
.Map(conf => conf.MapKey("NationID"))
.WillCascadeOnDelete(false);
}
}
Ce mappage créerait les deux clés étrangères OwnerID
et NationID
dans les NationAllies
table, les deux pointant vers la clé primaire ID
dans les Nations
tableau.
Modifier
Voici l'application avec laquelle j'ai testé :
- Créez une nouvelle application console dans VS2010/.NET 4.0, nommez-la "NationsApp"
- Ajouter une référence à "EntityFramework.dll"
- Effacez le contenu de "Program.cs" et collez à la place ce qui suit dans :
Contenu de Program.cs :
using System;
using System.Collections.Generic;
using System.Data.Entity;
namespace NationsApp
{
public class Nation
{
public int ID { get; set; }
public int name { get; set; }
public List<NationAlly> NationAllies { get; set; }
}
public class NationAlly
{
public int ID { get; set; }
public int level { get; set; }
public Nation toNation { get; set; }
}
public class NationsContext : DbContext
{
public DbSet<Nation> Nations { get; set; }
public DbSet<NationAlly> NationAllies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Nation>()
.HasMany(n => n.NationAllies)
.WithRequired()
.Map(conf => conf.MapKey("OwnerID"))
.WillCascadeOnDelete(false);
modelBuilder.Entity<NationAlly>()
.HasRequired(a => a.toNation)
.WithMany()
.Map(conf => conf.MapKey("NationID"))
.WillCascadeOnDelete(false);
}
}
class Program
{
static void Main(string[] args)
{
using (var context = new NationsContext())
{
try
{
// We have three Nations and two Allies
Nation nation1 = new Nation() {
NationAllies = new List<NationAlly>() };
Nation nation2 = new Nation() {
NationAllies = new List<NationAlly>() };
Nation nation3 = new Nation() {
NationAllies = new List<NationAlly>() };
NationAlly ally1 = new NationAlly();
NationAlly ally2 = new NationAlly();
// Nation1 has two Allies
// (Nation1 is the "owner" of both Allies)
nation1.NationAllies.Add(ally1);
nation1.NationAllies.Add(ally2);
// toNation of ally1 refers to Nation2
ally1.toNation = nation2;
// toNation of ally2 refers to Nation3
ally2.toNation = nation3;
context.Nations.Add(nation1);
context.Nations.Add(nation2);
context.Nations.Add(nation3);
context.SaveChanges();
}
catch (Exception e)
{
throw;
}
}
}
}
}
Vous pouvez définir un point d'arrêt sur "throw" pour surveiller les exceptions possibles dans e dans le débogueur.
Cela crée une base de données appelée NationsApp.NationsContext
si vous utilisez SQL Server Express et que vous n'avez défini aucune autre chaîne de connexion.
Cela donne deux relations Nation_NationAllies
(FK est "OwnerID") et NationAlly_toNation
(FK est "NationID"). Toutes les colonnes ne sont pas nullables. Le résultat dans la BD est le suivant :