簡體   English   中英

Entity Framework 7 多對多(相交表)“跳過導航”問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM