2017-02-12 25 views
1

私は、Entity Frameworkのコア1.1と次のエンティティとコンテキストを持って次のように私はその名の翻訳と言語を作成した後 Entity Frameworkのインスタンスを追跡することができません

public class Language { 
    public String LanguageCode { get; set; } 
    public virtual ICollection<LanguageI18N> LanguagesI18N { get; set; } = new List<LanguageI18N>(); 
} 

public class LanguageI18N { 
    public String LanguageCode { get; set; } 
    public String TranslationCode { get; set; } 
    public String Name { get; set; }   
    public virtual Language Language { get; set; } 
} 

public class Context : DbContext { 

    public DbSet<Language> Languages { get; set; } 
    public DbSet<LanguageI18N> LanguagesI18N { get; set; } 

    public Context(DbContextOptions options) : base(options) { } 

    protected override void OnModelCreating(ModelBuilder builder) { 

    base.OnModelCreating(builder); 

    builder.Entity<Language>(b => { 
     b.ToTable("Languages"); 
     b.HasKey(x => x.LanguageCode); 
     b.Property(x => x.LanguageCode).IsRequired(true).HasMaxLength(2).ValueGeneratedNever();   
    }); 

    builder.Entity<LanguageI18N>(b => { 
     b.ToTable("LanguagesI18N"); 
     b.HasKey(x => new { x.LanguageCode, x.TranslationCode });  
     b.Property(x => x.LanguageCode).HasMaxLength(2).IsRequired(true); 
     b.Property(x => x.TranslationCode).HasMaxLength(2).IsRequired(true); 
     b.HasOne(x => x.Language).WithMany(x => x.LanguagesI18N).HasForeignKey(x => x.LanguageCode).IsRequired(true).OnDelete(DeleteBehavior.Restrict); 
     b.HasOne(x => x.Language).WithMany(x => x.LanguagesI18N).HasForeignKey(x => x.TranslationCode).IsRequired(true).OnDelete(DeleteBehavior.Restrict);  
    });  

    } 

} 

public class Program { 

    public static void Main(String[] args) { 

    DbContextOptionsBuilder builder = new DbContextOptionsBuilder<Context>(); 

    builder.UseInMemoryDatabase(); 

    using (Context context = new Context(builder.Options)) { 

     Language language = new Language { LanguageCode = "en" }; 

     language.LanguagesI18N.Add(new LanguageI18N { LanguageCode = "en", TranslationCode = "en", Name = "English" }); 
     language.LanguagesI18N.Add(new LanguageI18N { LanguageCode = "en", TranslationCode = "pt", Name = "Inglês" }); 

     context.Languages.Add(language); 

     context.SaveChanges(); 

    }   

    } 

} 

私は英語とポルトガル語で "en"というコードとその名前の翻訳を作成しています。

私は、コードを実行すると、私は次のエラーを取得する:

Unhandled Exception: System.InvalidOperationException: The instance of entity type 'LanguageI18N' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities.
When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.

私は何をしないのですか?

UPDATE

コードは、インメモリデータベースとイワンStoevによって提案された変更で動作します:SQL Serverデータベースによって

builder.UseInMemoryDatabase(); 

::私はインメモリデータベースを交換したときに

b.HasOne<Language>().WithMany().HasForeignKey(x => x.TranslationCode).IsRequired(true).OnDelete(DeleteBehavior.Restrict); 

しかし

builder.UseSqlServer(yourConnectionString); 

私は次のエラーを取得する:

Unhandled Exception: Microsoft.EntityFrameworkCore.DbUpdateException: 
An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: 
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_LanguagesI18N_Languages_TranslationCode". 
The conflict occurred in database "TestDb", table "dbo.Languages", column 'LanguageCode'. 
The statement has been terminated. 

任意のアイデアなぜですか?ここで

+0

コンテキストオブジェクトをどのように作成していますか?注射されていますか? DIコンテナにどのように追加しましたか? – DavidG

+0

コンソールアプリケーションで接続文字列を使用してコンテキストを作成するだけで、言語テーブルの数を取得できるため、正常に動作しています。 –

+0

あなたは 'var context = new Context();'をどこかで実行しますか? (PSはコンテキストクラスの名前をContextに紛らわしいです!) – DavidG

答えて

2

b.HasOne(x => x.Language).WithMany(x => x.LanguagesI18N).HasForeignKey(x => x.LanguageCode).IsRequired(true).OnDelete(DeleteBehavior.Restrict); 
b.HasOne(x => x.Language).WithMany(x => x.LanguagesI18N).HasForeignKey(x => x.TranslationCode).IsRequired(true).OnDelete(DeleteBehavior.Restrict);  

あなたは1とLanguageで表さ同協会にマップしようとしている - ことは不可能である二つの異なるFKS(LanguageCodeTranslationCode)へ>LanguagesI18Nナビゲーションプロパティを、。 2行目は効果的に最初の行を上書きし、誤った設定につながります。

次の2つのone-to-many関係を有し、最初の行を仮定することは、第1の正しい設定が含まれているので、第二のに最後の行を変更することによって設定することができる:

b.HasOne<Language>().WithMany().HasForeignKey(x => x.TranslationCode).IsRequired(true).OnDelete(DeleteBehavior.Restrict); 

このようなセットアップ(W/OナビゲーションEF6では不可能でしたが、HasOne/HasManyメソッドのパラメータのないオーバーロードのおかげでEFコアで完全にサポートされました。モデルのナビゲーションプロパティと同期させてください(WithOne/WithMany)。

+0

あなたの提案は、InMemoryDatabaseでしか実際のSQLデータベースでは動作しません...少なくともそれはそうです。私は試したことを説明する質問にアップデートを追加しました。 –

+0

実際、新しい例外は、上記の動作 - 正しいFK制約が作成されたことを示します。あなたの挿入によって違反しました。つまり、 'Language'テーブルに存在しない' TranslationCode'を指定しましたか? –

+0

@IvanStoevはここにあります。言語コード 'pt'は言語テーブルに追加されないため、必要な関係のために特別に参照する子を追加することはできません。 – Smit

関連する問題