EntityFrameworkエンティティの外部キーの更新に問題があります。私は自己追跡エンティティを使用しており、外部キーがプロパティとしても存在するいくつかの関係を持つエンティティを持っています(EF4の新機能の1つ)。キー(整数)は、NullableおよびConcurrencyModefixedとしてマークされています。
具体的には、確認ユーザーとの関係が多対0..1のAlarmエンティティがあります。(ユーザーは複数のアラームを確認できますが、アラームを確認できるのは0人または1人のユーザーのみです)。
エンティティ定義(簡略化):
Alarm properties
Id Int32 non-nullable identity entity key
UserId Int32 nullable concurrency mode fixed
Alarm navigation properties
User 0..1 multiplicity
User properties
Id Int32 non-nullable identity entity key
Name String non-nullable
私の自己追跡エンティティでは、確認するユーザーIDは期待どおりにNullableとして自動生成されますが、ユーザーをすでに永続的なアラームに割り当ててApplyChangesを実行すると、自己追跡コンテキスト拡張機能は元の値(null)を設定しようとしますEFコンテキスト(コンテキスト拡張のSetValue内)ですが、EdmTypeのClrEquivalentTypeはnull許容ではないInt32であるため、サイレントにスキップします。
自動生成された拡張コード:
private static void SetValue(this OriginalValueRecord record, EdmProperty edmProperty, object value)
{
if (value == null)
{
Type entityClrType = ((PrimitiveType)edmProperty.TypeUsage.EdmType).ClrEquivalentType;
if (entityClrType.IsValueType &&
!(entityClrType.IsGenericType && typeof(Nullable<>) == entityClrType.GetGenericTypeDefinition()))
{
// Skip setting null original values on non-nullable CLR types because the ObjectStateEntry won't allow this
return;
}
}
int ordinal = record.GetOrdinal(edmProperty.Name);
record.SetValue(ordinal, value);
}
EFが後でアラームを更新しようとすると、UPDATEステートメントにWHERE句が作成され、正しい「is null」ではなく、元のユーザー外部キー値として0(ゼロ)が使用されるため、OptimisticConcurrencyExceptionが発生します。(WHERE句はEF楽観的同時実行メカニズムの一部であり、「固定」同時実行モードでマークされたプロパティの元の値がデータベース内のプロパティに対してチェックされます)。
null許容外部キー/プリミティブ型はEFの自己追跡エンティティで完全にはサポートされていませんか?そうでない場合、nullの代わりにダミーエンティティを使用することを強制されますか、それとも他の回避策がありますか?
更新 STEなしで問題を再現しようとしましたが、プレーンEFはnull許容外部キーに対して楽観的同時実行性をうまく処理しているようです。したがって、これはSTEの問題であり、EFの問題ではありません。自己追跡エンティティには多くの問題があるため、ここに不具合があるのは当然のことです。STE T4スクリプトで実装できる回避策を見つけたら、ここに投稿します。