データベース内の外部列名が、FK名のデフォルトの規則である。と一致しませんNavigationPropertyName_PrimaryKeyNameinTargetClass
。ナビゲーションプロパティが呼び出され、主キープロパティが呼び出されるためEnteredBy
、ModifiedBy
EFOperatorCode
は、前述の規則に従って、外部キー列として期待しEnteredBy_OperatorCode
ますModifiedBy_OperatorCode
。しかし、それらはデータベースに存在しないため、例外が発生します。EnteredBy
代わりに、FK列はとModifiedBy
です。
したがって、問題を修正するには、規則をオーバーライドする必要があります。
モデルにFKプロパティがない場合は、FluentAPIを使用します。
modelBuilder.Entity<Operator>()
.HasMany(o => o.ClientsEnteredBy)
.WithRequired(c => c.EnteredBy) // or HasOptional
.Map(m => m.MapKey("EnteredBy")); // mapping for the FK column name
modelBuilder.Entity<Operator>()
.HasMany(o => o.ClientsUpdatedBy)
.WithRequired(c => c.ModifiedBy) // or HasOptional
.Map(m => m.MapKey("ModifiedBy")); // mapping for the FK column name
(このマッピングを使用すると、InverseProperty
属性を削除できます。)
別のアプローチは、FKをモデルのプロパティとして公開することです。ナビゲーションプロパティの名前を変更し、FKプロパティにそれらの名前を使用します。その後、データ注釈を使用してマッピングが可能になります。
Client
クラスで:
[ForeignKey("EnteredByOperator")]
public string EnteredBy { get; set; }
[InverseProperty("ClientsEnteredBy")]
public virtual Operator EnteredByOperator { get; set; }
[ForeignKey("ModifiedByOperator")]
public string ModifiedBy { get; set; }
[InverseProperty("ClientsUpdatedBy")]
public virtual Operator ModifiedByOperator { get; set; }
そして、クラスのInverseProperty
属性を削除します。Operator
データ注釈の代わりに、FluentAPIを使用することもできます。
modelBuilder.Entity<Operator>()
.HasMany(o => o.ClientsEnteredBy)
.WithRequired(c => c.EnteredByOperator) // or HasOptional
.HasForeignKey(c => c.EnteredBy);
modelBuilder.Entity<Operator>()
.HasMany(o => o.ClientsUpdatedBy)
.WithRequired(c => c.ModifiedByOperator) // or HasOptional
.HasForeignKey(c => c.ModifiedBy);
両方の関係が必要な場合は、少なくとも1つの関係のカスケード削除を無効にする必要があります(.WillCascadeOnDelete(false)
いずれかのマッピングの最後に追加します)。そうしないと、SQL Serverは、テーブル間の複数のカスケード削除パスが許可されないというエラーをスローします。
ほとんどの場合、操作が簡単なので、「代替アプローチ」(プロパティとして外部キーを公開する)を使用することをお勧めします。