2008-11-21 8 views
11

Ich habe ein C# .net Winform-Programm, das mit einer SQL Server-Datenbank ausgeführt wird. Ich verwende LINQ-to-SQL. Ist es möglich, den Aufruf an eine oder mehrere gespeicherte Prozeduren innerhalb einer Transaktion in meinem Programm mithilfe von LINQ-to-SQL zurückzusetzen?Rollback eines gespeicherten Prozeduraufrufs innerhalb einer Transaktion mithilfe von LINQ-to-SQL?

Zunächst dachte ich, es wäre sinnvoll, die Transaktion innerhalb der gespeicherten Prozedur zu verwalten, aber wenn ich mehr als eine gespeicherte Prozedur Aufruf als Teil einer einzigen Transaktion Rollback muss in meinem C# -Programm durchgeführt werden.

Kann mir jemand auf ein Code-Snippet zeigen, wie man das macht oder einen Einblick in eine Alternative gibt?

Antwort

-1

Obwohl ich bin nicht gespeichert Procs verwenden, coudl Sie so etwas haben:

public Response<SomeObject> SaveSomething(Object yourObject) 
    { 
     DbTransaction dbTransaction = null; 
     try 
     { 
      using (DataContext context = new DataContext()) 
      { 
        //Creates a new DB transaction 
        if (context.Connection.State == System.Data.ConnectionState.Closed) 
        { 
         context.Connection.Open(); 
        } 
        dbTransaction = context.Connection.BeginTransaction(System.Data.IsolationLevel.Serializable); 
        context.Transaction = dbTransaction; 

     context.SaveYourObject(yourObject); 
        //Commit the transaction 
        dbTransaction.Commit(); 
        response.ResponseObject = yourObject; 
        response.Messages.AddSuccessfulSave("Saved!"); 
       } 
      } 
     } 
     catch (ChangeConflictException cex) 
     { 
      if (dbTransaction != null) dbTransaction.Rollback(); 
      response.Errors.AddConcurrencyError(); 
      response.IsSuccessful = false; 
     } 
     catch (SqlException sqlEx) 
     { 
      if (dbTransaction != null) dbTransaction.Rollback(); 
      if (sqlEx.Class == 14 && (sqlEx.Number == 2601 || sqlEx.Number == 2627)) //Duplicated key 
      { 
       response.Errors.Add(new Error 
       { 
        Name = "Duplicate item", 
        Description = "This object already exists." 
       }); 
       ExceptionPolicy.HandleException(sqlEx, SERVICE_EXCEPTION_POLICY); 
       response.IsSuccessful = false; 
      } 
      else //other SQL errors 
      { 
       response.Errors.AddSavingError("Your object", yourObjectId); 
       ExceptionPolicy.HandleException(sqlEx, SERVICE_EXCEPTION_POLICY); 
       response.IsSuccessful = false; 
      } 
     } 
15

Eine weitere Alternative zu DbTransaction ist TransactionScope - dies ein viel einfacheres Programmiermodell bietet, und ist erweiterbar auf mehrere gleichzeitige Datenbanken und andere Feeds (über DTC) - aber auf Kosten einer geringen Menge an Overhead auf der Verbindung. Es verwendet, um mehr Aufwand, aber unter SQL2005 usw. wird es die „LTM“ verwenden, bis Sie mehrere Verbindungen starten Spanning - so eine einzige Operation in der Regel sehr billig ist:

using (TransactionScope tran = new TransactionScope()) 
using (FooDataContext ctx = new FooDataContext()) 
{ 
    // your work with ctx 
    // ... 
    // other work involving connections etc 
    // ... 
    tran.Complete(); 
} 

Sehr einfache ;-p Sie sollten auch in der Lage sein, die Transaktion granularer zu machen (über nur ein paar Abfragen) oder mehr sehr einfach zu erfassen. Der meiste vorhandene Code wird automatisch in den Transaktionsumfang aufgenommen, wodurch es sehr einfach ist, ihn in vorhandenen Code nachzurüsten. Weitere Informationen über TransactionScope (und allgemeine Transaktionen in .NET) finden Sie unter here.

+2

Ich möchte nur einen Punkt klarstellen, wenn es nicht offensichtlich ist: "Die Complete-Methode schreibt die Transaktion fest. Wenn eine Ausnahme ausgelöst wurde, wird complete nicht aufgerufen und die Transaktion wird zurückgesetzt." (vom ersten Link oben) Gehen Sie also nicht nach 'rollback()' und haben Sie keine Codepfade, die ohne Complete() 'zurückkehren'. –

-2
private string RollBack_fn() 
{ 
    int sal = 0; 
    OracleConnection myconn = new OracleConnection(ConfigurationManager.AppSettings["con"].ToString()); 
    cmd = new OracleCommand("SP_student_MAST", myconn); 
    cmd.CommandType = CommandType.StoredProcedure; 
    OracleParameter param1 = null, param2 = null, param3 = null, param4 = null, param5 = null; 

    try 
    { 
     myconn.Open(); 
     trans = myconn.BeginTransaction(); 
     cmd.Transaction = trans; 
     //param1 = new OracleParameter("pSNo", OracleType.VarChar, 5); 
     //param1.Value =""; 
     //cmd.Parameters.Add(param1); 

     param2 = new OracleParameter("pSName", OracleType.VarChar, 10); 
     // param2.Value = "Saravanan"; 
     param2.Value = TextBox1.Text; 
     cmd.Parameters.Add(param2); 

     param3 = new OracleParameter("pENo", OracleType.VarChar,5); 
     param3.Value = TextBox2.Text; 
     cmd.Parameters.Add(param3); 

     param4 = new OracleParameter("pEName", OracleType.VarChar,10); 
     // param4.Value = "Sangeetha"; 
     param4.Value = TextBox3.Text; 
     cmd.Parameters.Add(param4); 

     param5 = new OracleParameter("pSENo", OracleType.Char, 5); 
     param5.Value = ""; 
     cmd.Parameters.Add(param5); 
     sal = cmd.ExecuteNonQuery(); 
     trans.Commit(); 
     Response.Write("Record Saved"); 
     myconn.Close(); 
     // rollbackvalue = 0; 
    } 
    catch (Exception ex) 
    { 
     Response.Write("Not saved.RollBacked"); 
     trans.Rollback(); 
     //rollbackvalue = 1; 
    } 
    string cs = Convert.ToString(sal); 
    return cs; 

}