Anda mungkin menjadi korban dari konvensi pemetaan EF Code-First yang secara otomatis membuat hubungan antara NationAllies
dan toNation
Anda tidak ingin memilikinya.
Jika saya memahami Anda dengan benar (tetapi saya tidak 100 persen yakin, jika saya memahaminya), Anda sebenarnya ingin memiliki dua hubungan dan Anda hanya mengekspos satu ujung hubungan di setiap entitas. Jadi, NationAllies
TIDAK menunjuk ke toNation
tetapi untuk negara Pemilik "tak terlihat" di NationAlly
. Anda entitas.
Jika demikian, Anda perlu secara eksplisit menimpa pemetaan konvensi. Di API Lancar EF 4.1 ini bisa terlihat seperti:
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);
}
}
Pemetaan ini akan membuat dua kunci asing OwnerID
dan NationID
di NationAllies
tabel, keduanya menunjuk ke kunci utama ID
di Nations
tabel.
Sunting
Berikut adalah aplikasi yang telah saya uji dengan:
- Buat Aplikasi Konsol baru di VS2010 / .NET 4.0, beri nama "NationsApp"
- Tambahkan referensi ke "EntityFramework.dll"
- Hapus konten "Program.cs" dan tempelkan yang berikut ini di:
Isi 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;
}
}
}
}
}
Anda dapat menyetel breakpoint pada "throw" untuk melihat kemungkinan pengecualian dalam e di debugger.
Ini membuat database bernama NationsApp.NationsContext
jika Anda menggunakan SQL Server Express dan tidak memiliki string koneksi lebih lanjut yang ditentukan.
Ini memberikan dua hubungan Nation_NationAllies
(FK adalah "OwnerID") dan NationAlly_toNation
(FK adalah "NationID"). Semua kolom tidak dapat dibatalkan. Hasil di DB adalah sebagai berikut: