0

在構建遷移我收到以下錯誤:實體框架的核心一對一的自參照關係失敗

無法確定按類型「位置」的導航屬性「Location.NorthLocation」表示的關係。要麼手動配置關係,要麼忽略模型中的該屬性。

的位置實體:

public class Location 
{ 
    public Guid Id { get; set; } 

    public DateTime CreatedWhen { get; set; } 
    public string CreatedBy { get; set; } 
    public DateTime ModifiedWhen { get; set; } 
    public string ModifiedBy { get; set; } 

    public Guid? NorthLocationId { get; set; } 
    public virtual Location NorthLocation { get; set; } 

    public Guid? SouthLocationId { get; set; } 
    public virtual Location SouthLocation { get; set; } 

    public Guid? EastLocationId { get; set; } 
    public virtual Location EastLocation { get; set; } 

    public Guid? WestLocationId { get; set; } 
    public virtual Location WestLocation { get; set; } 

} 

類型配置:

public class MyContext : DbContext 
{ 
    public MyContext(DbContextOptions<MyContext> options) : base(options) 
    { 
    } 

    public DbSet<Location> Locations { get; set; } 

    protected override void OnModelCreating(ModelBuilder builder) 
    { 
     base.OnModelCreating(builder); 

     builder.Entity<T>().HasKey("Id"); 
     builder.Entity<T>().Property("Id").ValueGeneratedOnAdd(); 
     builder.Entity<T>().Property("CreatedWhen").HasDefaultValueSql("GETDATE()").ValueGeneratedOnAdd(); 
     builder.Entity<T>().Property("ModifiedWhen").IsRequired(); 
     builder.Entity<T>().Property("CreatedBy").HasMaxLength(50).IsRequired(); 
     builder.Entity<T>().Property("ModifiedBy").HasMaxLength(50).IsRequired(); 

     // Locations 
     builder.Entity<Location>().HasOne(x => x.NorthLocation).WithOne(x => x.SouthLocation).HasForeignKey(typeof(Location), "NorthLocationId").OnDelete(DeleteBehavior.SetNull); 
     builder.Entity<Location>().HasOne(x => x.SouthLocation).WithOne(x => x.NorthLocation).HasForeignKey(typeof(Location), "SouthLocationId").OnDelete(DeleteBehavior.SetNull); 
     builder.Entity<Location>().HasOne(x => x.EastLocation).WithOne(x => x.WestLocation).HasForeignKey(typeof(Location), "EastLocationId").OnDelete(DeleteBehavior.SetNull); 
     builder.Entity<Location>().HasOne(x => x.WestLocation).WithOne(x => x.EastLocation).HasForeignKey(typeof(Location), "WestLocationId").OnDelete(DeleteBehavior.SetNull); 
    } 

} 

我的目標是有一個自我引用它自己的鄰居到北部一個位置實體/南/東/西。

任何人都可以提出爲什麼我可能會得到這個錯誤?

回答

0

您的模型配置不正確,因爲它將每個導航屬性都映射兩次。例如。 SouthLocation被映射爲NorthLocationId外鍵的逆向導航以及作爲SouthLocationId的直接導航。

每個導航屬性(即NorthLocation,SouthLocation,EastLocation,WestLocation)只能映射到一個關係(即在外鍵上)。

如果我刪除關係配置部分的第2行和第4行,模型似乎是功能性的。

一般來說,在EF Core中,我們嘗試通過讓最後一個配置執行win來處理衝突的配置,但這有一些限制,很難預測執行此代碼時可能發生的情況。當然,對於SQL Server使用EF Core 2.0 preview1,我得到了一個不同的異常(SQL Server的一個錯誤,抱怨cascade delte中的循環依賴),所以我們可以改進處理這種情況的方式。

這裏是代碼:

using System; 使用Microsoft.EntityFrameworkCore;使用Microsoft.EntityFrameworkCore.Metadata的 ;

namespace ConsoleApp4 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var db = new MyContext()) 
      { 
       db.Database.EnsureDeleted(); 
       db.Database.EnsureCreated(); 
      } 
     } 
    } 

    public class MyContext : DbContext 
    { 
     public DbSet<Location> Locations { get; set; } 
     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
     { 
      optionsBuilder.UseSqlServer(@"server=(localdb)\mssqllocaldb;database=hey;ConnectRetryCount=0"); 
     } 

     protected override void OnModelCreating(ModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<Location>().HasKey("Id"); 
      modelBuilder.Entity<Location>().Property("Id").ValueGeneratedOnAdd(); 
      modelBuilder.Entity<Location>().Property("CreatedWhen").HasDefaultValueSql("GETDATE()").ValueGeneratedOnAdd(); 
      modelBuilder.Entity<Location>().Property("ModifiedWhen").IsRequired(); 
      modelBuilder.Entity<Location>().Property("CreatedBy").HasMaxLength(50).IsRequired(); 
      modelBuilder.Entity<Location>().Property("ModifiedBy").HasMaxLength(50).IsRequired(); 
      modelBuilder.Entity<Location>().HasOne(x => x.NorthLocation).WithOne(x => x.SouthLocation).HasForeignKey(typeof(Location), "NorthLocationId").OnDelete(DeleteBehavior.Restrict); 
      modelBuilder.Entity<Location>().HasOne(x => x.EastLocation).WithOne(x => x.WestLocation).HasForeignKey(typeof(Location), "EastLocationId").OnDelete(DeleteBehavior.Restrict); 
     } 
    } 

    public class Location 
    { 
     public Guid Id { get; set; } 
     public DateTime CreatedWhen { get; set; } 
     public string CreatedBy { get; set; } 
     public DateTime ModifiedWhen { get; set; } 
     public string ModifiedBy { get; set; } 
     public Guid? NorthLocationId { get; set; } 
     public virtual Location NorthLocation { get; set; } 
     public Guid? SouthLocationId { get; set; } 
     public virtual Location SouthLocation { get; set; } 
     public Guid? EastLocationId { get; set; } 
     public virtual Location EastLocation { get; set; } 
     public Guid? WestLocationId { get; set; } 
     public virtual Location WestLocation { get; set; } 
    } 
} 
+0

如果這兩行被排除在外如何處理相應的外鍵我會屬性?是否足夠聰明地弄清楚並填充它們呢? – Hades

+0

您只能在數據庫中爲每個南北和每個東西方關係確實擁有一個FK。選擇何處定位FK(例如,北或南行)是完全任意的。這反過來又是一個關係數據庫設計問題,而不是EF核心問題。順便說一下,我還沒有提到它,但我不確定跟蹤南北和東西方關係是模擬實際地理分佈位置的好方法。 – divega

+0

我嘗試刪除這兩行,它仍然爲我引發相同的錯誤。這是一個戰略遊戲的空間地圖。基本上我想有能力在任何方向「旅行」。 – Hades