2013-09-27 8 views
5

मुझे इकाई ढांचे LINQ का उपयोग करके एसक्यूएल अपवादों के बीच अंतर करने का एक तरीका चाहिए, उदाहरण के लिए, जब मैं DbUpdateException से प्राप्त करता हूं तो डीबीअपडेट एक्सेप्शन से प्राप्त होने पर अनन्य बाधा उल्लंघन का अंतर कैसे करना है, अपवाद और बेकार लंबे त्रुटि संदेश? क्या कोई निम्न स्तर अपवाद है जहां मैं कुछ कर सकता हूं जैसे "एफकेएक्सप्शन पकड़ो"; "अद्वितीय अपवाद" या उस तरह कुछ पकड़ो।इकाई ढांचे में हैंडल अपवाद 4

+0

अक्सर आंतरिक अपवादों में संख्यात्मक त्रुटि कोड होंगे, क्या आपने उनको देखने की कोशिश की है? अपने प्रश्न में अपवाद का उदाहरण पोस्ट करें, टेक्स्ट को हाइलाइट करना सुनिश्चित करें और इसे प्रारूप बनाने के लिए '{}' बटन पर क्लिक करें। –

उत्तर

5

एसक्यूएल त्रुटि कोड का उपयोग करना ...

catch (DbUpdateException ex) 
        { 
         var sqlex = ex.InnerException.InnerException as SqlException; 

         if (sqlex != null) 
         { 
          switch (sqlex.Number) 
          { 
           case 547: throw new ExNoExisteUsuario("No existe usuario destino."); //FK exception 
           case 2627: 
           case 2601: 
            throw new ExYaExisteConexion("Ya existe la conexion."); //primary key exception 

           default: throw sqlex; //otra excepcion que no controlo. 


          } 
         } 

         throw ex; 
        } 
11
  try 
      { 
       //code 
      } 
      catch (System.Data.Entity.Validation.DbEntityValidationException e) 
      { 
       string rs = ""; 
       foreach (var eve in e.EntityValidationErrors) 
       { 
        rs = string.Format("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", eve.Entry.Entity.GetType().Name, eve.Entry.State); 
        Console.WriteLine(rs); 

        foreach (var ve in eve.ValidationErrors) 
        { 
         rs += "<br />" + string.Format("- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage); 
        } 
       } 
       throw new Exception(rs); 
      } 
+4

यदि आप वास्तव में दयालु होना चाहते हैं तो आखिरी पंक्ति 'नई अपवाद (आरएस, ई)' फेंकनी चाहिए, इसलिए चेन का अगला व्यक्ति आंतरिक अपवाद की जांच कर सकता है और स्टैकट्रैक और व्हाट्नॉट देख सकता है। (सामान्य 'अपवाद' के बजाय एक कस्टम अपवाद भी फेंकना अच्छा होगा) –

+0

लेकिन मुझे वास्तव में उनके बीच अंतर करने की आवश्यकता है, मुझे किस प्रकार की डेटाबेस त्रुटि के आधार पर विभिन्न अपवादों को फेंकने की आवश्यकता है। – user1777914

1

मैं इस के लिए जोड़े को उपयोगिता तरीकों लिखा है:

public static class DbUtils 
{ 
    /// <summary> 
    ///  Takes a code block that updates database, runs it and catches db exceptions. If the caught 
    ///  exception is one of those that are ok to ignore (okToIgnoreChecks) then no 
    ///  exception is raised and result is returned. Otherwise an exception is rethrown. 
    /// 
    ///  This function is intended to be run within an explicit transaction, i.e.: 
    ///  using (var transaction = db.Database.BeginTransaction()), which should be committed/rolledback afterwards. 
    ///  Otherwise, if you don't use a transaction discard the db context or in other words make this operation 
    ///  the only one that you run within implicit transaction. 
    /// 
    ///  This function can wrap a single DB statement, but it's more efficient to wrap multiple statements 
    ///  so that locks are held for shorter period of time. 
    ///  If an exception occurs within a transaction and is caught by this function, all other changes 
    ///  will be still saved to DB on commit if transaction is used. 
    /// </summary> 
    /// <typeparam name="T">Any result returned by the code block</typeparam> 
    /// <param name="context">Database connection</param> 
    /// <param name="dbCodeBlock"> 
    ///  Code block to execute that updates DB. It's expected, but not critical that 
    ///  this code does not throw any other exceptions. Do not call SaveChanges() from the code block itself. Let this 
    ///  function do it for you. 
    /// </param> 
    /// <param name="okToIgnoreChecks"> 
    ///  List of functions that will check if an exception can be ignored. 
    /// </param> 
    /// <returns>Returns number of rows affected in DB and result produced by the code block</returns> 
    public static Tuple<int, T> IgnoreErrors<T>(DbContext context, 
     Func<T> dbCodeBlock, params Func<DbUpdateException, bool>[] okToIgnoreChecks) 
    { 
     var result = dbCodeBlock(); 
     try 
     { 
      var rowsAffected = context.SaveChanges(); 
      return Tuple.Create(rowsAffected, result); 
     } 
     catch (DbUpdateException e) 
     { 
      if (okToIgnoreChecks.Any(check => check(e))) 
       return Tuple.Create(0, result); 
      throw; 
     } 
    } 

    public static bool IsDuplicateInsertError(DbUpdateException e) 
    { 
     return GetErrorCode(e) == 2601; 
    } 

    public static bool IsForeignKeyError(DbUpdateException e) 
    { 
     return GetErrorCode(e) == 547; 
    } 

    public static T UpdateEntity<T>(DbContext context, T entity, Action<T> entityModifications) 
     where T : class 
    { 
     return EntityCrud(context, entity, (db, e) => 
     { 
      db.Attach(e); 
      entityModifications(e); 
      return e; 
     }); 
    } 

    public static T DeleteEntity<T>(DbContext context, T entity) 
     where T : class 
    { 
     return EntityCrud(context, entity, (db, e) => db.Remove(e)); 
    } 

    public static T InsertEntity<T>(DbContext context, T entity) 
     where T : class 
    { 
     return EntityCrud(context, entity, (db, e) => db.Add(e)); 
    } 

    public static T EntityCrud<T>(DbContext context, T entity, Func<DbSet<T>, T, T> crudAction) 
     where T : class 
    { 
     return crudAction(context.Set<T>(), entity); 
    } 
} 

यहाँ है कैसे आप इसका इस्तेमाल कर सकते हैं। संभावित डुप्लिकेट पंक्ति डालने का उदाहरण:

DbUtils.IgnoreErrors(_db,() => DbUtils.InsertEntity(_db, someEntity), 
    DbUtils.IsDuplicateInsertError); 

कोई अपवाद नहीं फेंक दिया जाएगा।

पिछले उदाहरण की तरह, लेकिन संभाल FK उल्लंघन स्पष्ट रूप से अपवाद:

 try 
     { 
      var numInserted = DbUtils.IgnoreErrors(_db,() => DbUtils.InsertEntity(_db, someEntity), DbUtils.IsDuplicateInsertError).Item1; 
      // no FK exception, but maybe unique index violation, safe 
      // to keep going with transaction 
     } 
     catch (DbUpdateException e) 
     { 
      if (DbUtils.IsForeignKeyError(e)) 
      { 
       // you know what to do 
      } 
      throw; // rethrow other db errors 
     } 

अंततः आप अगर आप एक स्पष्ट लेन-देन है लेन-देन के लिए प्रतिबद्ध कॉल कर सकते हैं, अन्यथा बचाने पहले से ही संदर्भ पर बुलाया गया है।

संबंधित मुद्दे