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