Du är kanske ett offer för EF Code-First-mappningskonventionerna som automatiskt skapar en relation mellan NationAllies
och toNation
du inte vill ha.
Om jag förstår dig rätt (men jag är inte 100 procent säker, om jag gör det) så vill du faktiskt ha två relationer och du har bara exponerat ena änden av relationen i var och en av entiteterna. Så, NationAllies
pekar INTE på toNation
men till en "osynlig" Ägarnation i din NationAlly
enhet.
Om så är fallet måste du explicit skriva över konventionsmappningarna. I Fluent API för EF 4.1 kan detta se ut så här:
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);
}
}
Denna mappning skulle skapa de två främmande nycklarna OwnerID
och NationID
i NationAllies
tabell, båda pekar på primärnyckeln ID
i Nations
bord.
Redigera
Här är applikationen jag har testat med:
- Skapa en ny konsolapp i VS2010 / .NET 4.0, döp den till "NationsApp"
- Lägg till en referens till "EntityFramework.dll"
- Rensa innehållet i "Program.cs" och klistra istället in följande i:
Innehåll i 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;
}
}
}
}
}
Du kan ställa in en brytpunkt på "kast" för att se möjliga undantag i e i felsökaren.
Detta skapar en databas som heter NationsApp.NationsContext
om du använder SQL Server Express och inte har några ytterligare anslutningssträngar definierade.
Det ger två relationer Nation_NationAllies
(FK är "OwnerID") och NationAlly_toNation
(FK är "NationID"). Alla kolumner är ej nullbara. Resultatet i DB är följande: