Možná jste obětí mapovacích konvencí EF Code-First, které automaticky vytvářejí vztah mezi NationAllies
a toNation
nechcete mít.
Pokud vám správně rozumím (ale nejsem si 100 procent jistý, pokud ano), chcete mít ve skutečnosti dva vztahy a v každé z entit jste odhalili pouze jeden konec vztahu. Takže NationAllies
NEUkazuje na toNation
ale na "neviditelný" národ vlastníka ve vašem NationAlly
entity.
Pokud je to váš případ, musíte explicitně přepsat mapování konvence. V rozhraní Fluent API EF 4.1 by to mohlo vypadat takto:
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);
}
}
Toto mapování by vytvořilo dva cizí klíče OwnerID
a NationID
v NationAllies
tabulka, oba ukazují na primární klíč ID
v Nations
tabulka.
Upravit
Zde je aplikace, se kterou jsem testoval:
- Vytvořte novou konzolovou aplikaci ve VS2010 / .NET 4.0, pojmenujte ji „NationsApp“
- Přidejte odkaz na "EntityFramework.dll"
- Vymažte obsah souboru „Program.cs“ a vložte do něj následující:
Obsah 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;
}
}
}
}
}
Můžete nastavit bod přerušení na "throw", abyste sledovali možné výjimky v e v ladicím programu.
Tím se vytvoří databáze s názvem NationsApp.NationsContext
pokud používáte SQL Server Express a nemáte definovány žádné další připojovací řetězce.
Poskytuje dva vztahy Nation_NationAllies
(FK je "OwnerID") a NationAlly_toNation
(FK je "NationID"). Všechny sloupce nemají hodnotu null. Výsledek v DB je následující: