2012-04-21 6 views
-1

私はcountriesという名前のテーブルを持っています。 "をSQL Server 2008 r2の" Unique Key "とタイプします。 しかし、現在、ユーザーがasp.net mvc3アプリケーションにすでに存在するcountry_name値を挿入すると、 "System.Data.Entity.Infrastructure.DbUpdateException"型の例外が発生します。これは非常に一般的です。私は、ユニークなキー制約がthr SQLサーバーデータベースで違反された場合、エンティティフレームワークに一意の例外を発生させることができます

ユニークな制約が違反された場合に備えて、特定の例外を定義する方法はありますか?単に一般的な "System.Data.Entity.Infrastructure.DbUpdateException"例外を送出するのではなく、

BR

答えて

2

ほとんどの場合は、私は、現時点ではそれをテストすることはできませんと思った、DbUpdateExceptionの内部例外は、おそらく重複または外部キー制約については例外です。さらに重要なのは、ある国がすでに存在するかどうかを確認することによって例外をスローしないことです。私が考えることができる2つの方法は、その国がすでに存在するかどうかをチェックして確認し、そうでない場合は、ストアドプロシージャの挿入/追加または書き込みを行い、選択/挿入またはマージして元に戻す値を返します。

更新

例外ロジック(これは、イベントの論理フローはなく、良好なプログラミング方法を示すためのコード例は、特別にすべてexceptsで捕捉することによる)

public AddCountry(string countryTitle) 
{ 
    using (var db = new DbContext(_connectionString) 
    { 
    try 
    { 
     // Linq to (SQL/EF)-ish code 
     Country country = new Country(); 
     country.ID = Guid.NewGuid(); 
     country.Title = countryTitle; 
     db.Countrys.Add(country); 
     db.SubmitChanges(); // <--- at this point a country could already exist 
    } 
    catch (DbUpdateException ex) 
    { 
     // <--- at this point a country could be delete by another user 
     throw Exception("Country with that name already exists"); 
    } 
    } 
} 

非例外ロジック

public AddCountry(string countryTitle) 
{ 
    using (var db = new DbContext(_connectionString) 
    { 
    using (TransactionScope transaction = new TransactionScope()) 
    { 
     try 
     { 
     Country country = db.Countries 
          .FirstOrDefault(x => x.Title = countryTitle); 

     if (country == null) 
     { 
      country = new Country(); 
      country.ID = Guid.NewGuid(); 
      country.Title = countryTitle; 
      db.Countrys.Add(country); 
      db.SubmitChanges(); // <--- at this point a country 
           // shouldn't exist due to the transaction 
           // although someone with more expertise 
           // on transactions with entity framework 
           // would show how to use transactions properly 
     } 
     } 
     catch (<someTimeOfTransactionException> ex) 
     { 
     // <--- at this point a country with the same name 
     // should not exist due to the transaction 
     // this should really only be a deadlock exception 
     // or an exception outside the scope of the question 
     // (like connection to sql lost, etc) 
     throw Exception("Deadlock exception, cannot create country."); 
     } 
    } 
    } 
} 

ほとんどの場合、TransactionScope(Transaction transactionToUse) Constructorが適切に設定されている必要があります。 Probably with an Transactions.IsolationLevel set to Serializable

Entity Framework transactionもお勧めします。

+0

返信いただきありがとうございます。私は、選択アプローチを使用すると、複数のユーザーが同じ国名を同時に追加したり削除したりする場合、100%の正確な結果を得られない可能性があるため、例外的なアプローチを使用して、私は使用すべきではないはずの悪い習慣と考えていますか? –

+0

私の個人的な意見では、誰かがランタイム例外ロジックを使用するか使用しないかを決定するそれぞれのインスタンスは、理想的な場合とそうでない場合があります。この特定の例では、例外ロジックは私が説明した選択肢から追加の利益を提供するものではありません。なぜ私はそれが信じているのかと私の答えを更新します。 –

+0

返事をありがとう、私はあなたのポイントを理解したと思う。私のアプローチでは、.save()を実行して例外を発生させる間に削除された国のレコードが頻繁に発生する可能性がありますが、誤ったエラーメッセージが表示される可能性があります。 ?私は正しい? –

関連する問題