2017-10-29 11 views
0

Entity Framework v6を使用するMVCアプリケーションがあります。我々はクラスを持っていますEntity Frameworkによる断続的な問題望まない行の作成

public class ChildObject 
{ 
    public string Name { get; set; } 
    .... 
} 

これは、データベースのテーブルにマップします。この表には決して変更されない6行があります。そこにも追加はありません。 ParentClassオブジェクトが作成または更新されるたびに

public class ParentClass 
{ 
    public int ChildObjectId { get; set; } 
    public ChildObject ChildObject { get; set; } 
    .... 
} 

が論理だけChildObjectIdプロパティを参照しています。我々は、次の線に沿って定義された第二のクラスを持っています。 ChildObjectプロパティは、データを引き出して表示するときにのみ参照されます。ただし、月に約1回、既存の行の複製であるChildObject表に余分な行が表示されます。これは明らかに問題を引き起こします。しかし、私はId値を使って保存するだけで、これがどのように見えるのか分かりません。これがどのように起こっているかについてのいかなる考えも非常に高く評価されるだろう。

+0

あなたは誰かがそのプロパティにそのオブジェクトを割り当てている場所があり、割り当てられたオブジェクトのIDが0であるように聞こえるので、 'ChildObject ='の解決策を探しましたか? –

+0

はい、サイト全体の検索を行ったそれはまさに私が思っていたものであった – fhevol

答えて

1

説明するような動作の一般的な原因は、新しい子エンティティが既存のデータに基づいて構成され、コンテキストに関連付けられた参照ではなく親に接続される場合です。たとえば、子オブジェクトを選択してセットとしてロードし、ビューにデータを送信する場合があります。ユーザーは、既存の子参照を6つの選択肢の1つに変更したいと考えています。

parent.ChildObject = new ChildObject{ Name = model.Name, ... } 

いうより:

var child = context.Children.Single(x => x.Id = model.ChildObjectId); 
parent.ChildObject = child; 

ドメインを使用すると、シナリオに実行することが設定されている方法に応じてコールバックサーバへのようなコードの何かがある子オブジェクトモデルを渡しますEFコンテキストは、ナビゲーションプロパティが設定されているときに新しい子エンティティを作成します。 ChildObjectプロパティのFindUsagesで確認し、セッターの使用方法を探します。

一般的に、FKプロパティ(ChildObjectId)とナビゲーションプロパティ(ChildObject)の組み合わせは避けてください。ナビゲーションリファレンスで設定されているものとFKとの間で動作が混乱する可能性があります。エンティティはどちらか一方で定義する必要があります。 (この時点では、ナビゲーションプロパティを使用する場合はEF Coreが必要です)

例のカップルの名前: ナビゲーションプロパティを仮想としてマークする - EFがプロキシを割り当てて認識するようにします。

オプションA - FK子IDプロパティを削除します。親のためにどちらかのFK列をマップするためにDbContextをEntityTypeConfigurationを使用するか、または初期化:

EntityTypeConfiguration:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<ParentObject>().HasRequired(x => x.ChildObject).WithMany().Map(x => x.MapKey("ChildObjectId")).WillCascadeOnDelete(false); 
} 

またはOption(あなたのDbContextインサイド):

public class ParentClassConfiguration : EntityTypeConfiguration<ParentClass> 
{ 
    public ParentClassConfiguration() 
    { 
    ToTable("ParentTable"); 
    HasKey(x => x.ParentObjectId) 
     .Property(x => x.ParentObjectId) 
     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

    HasRequired(x => x.ChildObject) 
     .WithMany() 
     .Map(x => x.MapKey("ChildObjectId")); 
     .WillCascadeOnDelete(false); 
    } 
} 

またはコンテキストモデル生成に

B - FKが参照にリンクされていることを確認し、2つが常に同期していることを確認するための対策を講じる:

public class ParentClassConfiguration : EntityTypeConfiguration<ParentClass> 
{ 
    public ParentClassConfiguration() 
    { 
    ToTable("ParentTable"); 
    HasKey(x => x.ParentObjectId) 
     .Property(x => x.ParentObjectId) 
     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

    HasRequired(x => x.ChildObject) 
     .WithMany() 
     .HasForeignKey(x => x.ChildObjectId)); 
     .WillCascadeOnDelete(false); 
    } 
} 

またはコンテキストモデル生成について:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<ParentObject>().HasRequired(x => x.ChildObject).WithMany().HasForeignKey(x => x.ChildObjectId)).WillCascadeOnDelete(false); 
} 

オプションB(あなたDbContextの内部では)私の知る限りではEFコアと、現在入手可能な唯一のものであり、それはあなたの問題を軽減するのに役立つかもしれませんが、あなたはまだ世話をする必要がありナビゲーションプロパティとFKとの間の相違を避けるためです。私は間違いなくオプションAをお勧めしますが、あなたのコードが一般的にFK列にアクセスしている場合は、少し変更が必要になるでしょう。

関連する問題