Có lẽ bạn là nạn nhân của quy ước ánh xạ EF Code-First vốn tự động tạo ra mối quan hệ giữa NationAllies
và toNation
bạn không muốn có.
Nếu tôi hiểu bạn đúng (nhưng tôi không chắc 100 phần trăm, nếu tôi hiểu), thì bạn thực sự muốn có hai mối quan hệ và bạn chỉ để lộ một đầu mối quan hệ trong mỗi thực thể. Vì vậy, NationAllies
KHÔNG trỏ đến toNation
nhưng với quốc gia Chủ sở hữu "vô hình" trong NationAlly
của bạn thực thể.
Nếu trường hợp đó xảy ra, bạn cần ghi đè rõ ràng các ánh xạ quy ước. Trong API Fluent của EF 4.1, điều này có thể giống như sau:
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);
}
}
Ánh xạ này sẽ tạo ra hai khóa ngoại OwnerID
và NationID
trong NationAllies
bảng, cả hai đều trỏ đến khóa chính ID
trong Nations
bảng.
Chỉnh sửa
Đây là ứng dụng tôi đã thử nghiệm:
- Tạo Ứng dụng bảng điều khiển mới trong VS2010 / .NET 4.0, đặt tên là "NationsApp"
- Thêm tham chiếu vào "EntityFramework.dll"
- Xóa nội dung của "Program.cs" và thay vào đó dán nội dung sau vào:
Nội dung của 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;
}
}
}
}
}
Bạn có thể đặt điểm ngắt trên "ném" để xem các ngoại lệ có thể xảy ra ở e trong trình gỡ lỗi.
Điều này tạo ra một cơ sở dữ liệu có tên là NationsApp.NationsContext
nếu bạn đang sử dụng SQL Server Express và không có bất kỳ chuỗi kết nối nào được xác định.
Nó cung cấp hai mối quan hệ Nation_NationAllies
(FK là "OwnerID") và NationAlly_toNation
(FK là "NationID"). Tất cả các cột đều không thể null. Kết quả trong DB như sau: