[英]Entity Framework 7 Many-To-Many (intersect table) "skip navigation" problem
我正在將一個項目從 NHibernate 遷移到 EF,我剛剛開始使用 EF7。 由於它是新的,因此似乎沒有很多專門針對此的帖子。 我在舊的 EF 版本上找到了幾個,但它們不適用/工作。 我很難使用相交表配置多對多關系我基本上逐字使用這個例子,但我收到一個運行時錯誤,說我的對象的屬性沒有外鍵。
我的對象如下:
public partial class Casino
{
// other properties
private IList<Country> _prohibitedCountries;
public IList<Country> ProhibitedCountries
{
get { return _prohibitedCountries; }
protected set { _prohibitedCountries = value; }
}
}
public partial class Country
{
// other properties
private IList<Casino> _prohibitedCasinos;
public IList<Casino> ProhibitedCasinos
{
get { return _prohibitedCasinos; }
protected set { _prohibitedCasinos = value; }
}
}
所以一個賭場可以有許多被禁止的國家,反之亦然。
我的數據庫上下文定義如下:
public class DsDbContext : DbContext
{
public DbSet<Casino> Casinos { get; set; }
public DbSet<Country> Countries { get; set; }
// Other collections...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var connectionString = configuration.GetConnectionString("DataStoreDatabase");
optionsBuilder.UseSqlServer(connectionString);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Casino>()
.HasMany(a => a.ProhibitedCountries)
.WithMany(b => b.ProhibitedCasinos)
.UsingEntity<Dictionary<string, object>>(
"Casino_Prohibited_Country",
j => j
.HasOne<Country>()
.WithMany()
.HasForeignKey("CountryId")
.HasConstraintName("FK_CasinoProhibitedCountry_Country")
.OnDelete(DeleteBehavior.Cascade) ,
j => j
.HasOne<Casino>()
.WithMany()
.HasForeignKey("CasinoId")
.HasConstraintName("FK_CasinoProhibitedCountry_Casino")
.OnDelete(DeleteBehavior.Cascade)
);
modelBuilder
.Entity<Country>()
.HasMany(c => c.ProhibitedCasinos)
.WithMany(c => c.ProhibitedCountries)
.UsingEntity<Dictionary<string, object>>(
"Casino_Prohibited_Country",
j => j
.HasOne<Casino>()
.WithMany()
.HasForeignKey("CasinoId")
.HasConstraintName("FK_CasinoProhibitedCountry_Casino")
.OnDelete(DeleteBehavior.Cascade),
j => j
.HasOne<Country>()
.WithMany()
.HasForeignKey("CountryId")
.HasConstraintName("FK_CasinoProhibitedCountry_Country")
.OnDelete(DeleteBehavior.Cascade)
);
}
這是顯示約束和 FK 的相交表的腳本。 我不希望像這樣有一個對應於每個相交表的實體。 我確實嘗試了該配置並得到了完全相同的運行時錯誤
CREATE TABLE [dbo].[Casino_Prohibited_Country](
[CasinoId] [int] NOT NULL,
[CountryId] [int] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Casino_Prohibited_Country] WITH NOCHECK ADD CONSTRAINT [FK_CasinoProhibitedCountry_Casino] FOREIGN KEY([CasinoId])
REFERENCES [dbo].[Casino] ([Id])
GO
ALTER TABLE [dbo].[Casino_Prohibited_Country] CHECK CONSTRAINT [FK_CasinoProhibitedCountry_Casino]
GO
ALTER TABLE [dbo].[Casino_Prohibited_Country] WITH NOCHECK ADD CONSTRAINT [FK_CasinoProhibitedCountry_Country] FOREIGN KEY([CountryId])
REFERENCES [dbo].[Country] ([Id])
GO
ALTER TABLE [dbo].[Casino_Prohibited_Country] CHECK CONSTRAINT [FK_CasinoProhibitedCountry_Country]
GO
當我執行僅執行一些基本 CRUD 操作的單元測試時,我在基本存儲庫的構造函數中遇到運行時錯誤
public BaseRepository(DsDbContext context)
{
_context = context;
_dbSet = context.Set<TEntity>(); // The error below is thrown on this line
}
System.InvalidOperationException: 'The skip navigation 'Country.ProhibitedCasinos' doesn't have a foreign key associated with it. Every skip navigation must have a configured foreign key.'
我不明白為什么 EF 在配置中明確說明時找不到外鍵。 EF 能夠訪問數據庫並讀取沒有關系的實體的記錄
我在EFCore github 存儲庫上找到了來自 Microsoft 工程師的(非常違反直覺的)解決方案
本質上,我需要做的是刪除這個: .HasConstraintName("FK_CasinoProhibitedCountry_Country")
當錯誤消息是:
System.InvalidOperationException: 'The skip navigation 'Country.ProhibitedCasinos' doesn't have a foreign key associated with it. Every skip navigation must have a configured foreign key.'
另一個變化與 Ivan Stoev 在他的評論中建議的一致:刪除第二個定義。
下面是新的/工作配置。 請注意MS 文檔中缺少的HasConstraintName
設置。 另外請注意,這僅在 Casino 實體上配置,而不是在 Country 實體上進行反向配置。
modelBuilder.Entity<Casino>()
.HasMany(e => e.ProhibitedCountries)
.WithMany(e => e.ProhibitedCasinos)
.UsingEntity<Dictionary<string, object>>(
"Casino_Prohibited_Country",
e => e
.HasOne<Country>()
.WithMany()
.HasForeignKey("CountryId"),
e => e
.HasOne<Casino>()
.WithMany()
.HasForeignKey("CasinoId")
);
git 的 MS 工程師建議從Casino_Prohibited_Country
相交表的兩列創建復合主鍵,但我沒有這樣做,但它仍然有效,所以這似乎沒有必要
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.