データベースに 2 つのテーブルがあります。表 USER および表 USER_ADDRESSES
表 USER には UserID 、 UserName 、 HumanName があります
テーブル USER_ADDRESSES には、UserAddresseID、UserID、Address があります。
2 つのテーブルは、UserID 外部キーによって関連付けられています。
私は最初にコードを作業しています。POCOは、私が推測するとおりです。
Public class User
{
Public guid UserID {get;set;}
Public string UserName {get;set;}
Public string HumanName {get;set;}
}
Public class UserAddress
{
Public guid UserAddressID {get;set;}
Public guid UserID {get;set;}
Public string Address {get;set;}
Public virtual User User {get;set;}
}
ユーザーをPOSTすると、EFを介して物理データベースに流れます-クール
上記のユーザーのUserIDとして適切に割り当てられたUserID外部キーを使用してUserAddressをPOSTすると、userAddressはEFを介して物理データベースに流れます-完璧です。
このテーマを学んでいる今、エラーが発生することがわかっているシナリオをテストするのが好きです...何かが失敗する方法を理解することで、理解が深まります (IMHO)。
この目的のために、上記の手順を繰り返します。ユーザーを POST してからアドレスを POST しますが、今回は Address.UserID プロパティに空の GUID を指定すると、SQL サーバーでエラーが発生することがわかっています。今回は EF でエラーが返されます。 DB から、コントローラ クラスでそのエラーを DbUpdateException として表示します。これに基づいて、BadRequest ErrorResponse を送り返します。DB に何も投稿できない場合を除いて、これは問題ありません。その後、新しいユーザー EF を投稿しようとすると、すべての POST で DbUpdateException をスローします。この状態から抜け出す唯一の方法は、WebAPI プロジェクトのデバッグを停止し、IISExpress を強制終了して、すべてを再起動することです。
私の疑いは、dbset.Local で追跡されたエンティティと関係があるということです。このコレクションは、データベースの制約に違反するエンティティを喜んで格納しているように見えます。DB がエラーをスローした後でも、EF は障害のあるエンティティをキャッシュから削除しません。 、そして DataContext.SaveChanges() を呼び出すたびに、EF は bdset.Local プロパティにある Faulty アドレス エンティティを送信しようとし続けるため、プロジェクト全体が再起動されるまで DB にそれ以上送信できないと思います。さまざまな dbset.Local コレクションがフラッシュされます。
わかりました、コントローラークラスでは、オブジェクトのさまざまなプロパティを評価してからリポジトリ/ UnitOfWork に送信することで、これらの問題のいくつかを防ぐことができるため、そもそも dbset.Local に入るのを防ぐことができます。 UserAddress エンティティで UserID == Guid.Empty の場合に ModelState.IsValid が false を返すように、POCO に追加できるいくつかの装飾??? . しかし、確実に EF は DB に起因するエラーから回復できるはずです。たとえば、SQL サーバーに対して実行されたときに INSERT ステートメントが失敗した場合、EF は追跡されたオブジェクトのローカル キャッシュから障害のあるエンティティを削除する必要があります。したがって、システム全体を完全に再起動する必要がなくなります。これの結果は、他の非キー フィールドに一意の制約がある場合、エンティティを送信しようとする前に、DB にクエリを実行して、DBUdateException がスローされる原因となるレコードが DB にないことを確認する必要があります。そのアプローチは私には非効率的です。私はむしろエラーを取り、それをクライアントに返して検討してもらいたいと思います。
おそらく、DbUpdateException が発生したときに、障害のあるエンティティを dbset.Local コレクションなどから削除するのは私の責任です。この場合、どうすればいいのでしょうか?
私がこれを書いているとき、私は不思議に思っています: EF はそれ自体で DBUdateExceptions から回復できないはずです!? IIS を再起動する必要はありません。または、これまでにない制約なしで DB を構築し、クライアントが古いごみをそこに入れることを許可する必要があります。EF エンティティの追跡は、db の制約を尊重し、障害のあるエンティティがそもそも dbset に入らないようにする必要があると私は信じています。
DBUpdateException から回復する正しい方法を教えてください。