Как поместить эти вызовы в SqlTransaction? - PullRequest
3 голосов
/ 08 ноября 2010

У меня есть класс со всем моим кодом доступа к данным для моего приложения ASP.NET 4.0. В классе есть два метода, которые вставляют данные в базу данных. Я хочу включить эти вставки в SqlTransaction и откатить транзакцию в случае сбоя одной из вставок. Однако я не уверен, как это сделать, из-за того, как я это кодировал. Вот мой код доступа к данным:

public class DBUtil
{

    private static readonly string _connectionString;

    static DBUtil()
    {
        _connectionString = WebConfigurationManager.ConnectionStrings["MooDB"].ConnectionString;
        if (string.IsNullOrEmpty(_connectionString))
            throw new Exception("Connection string not configured in Web.Config file");
    }

    public int InsertTrade(
        string symbol,
        string tradeSetupId,
        int tradeTypeId,
        decimal lotsPerUnit,
        string chartTimeFrame,
        decimal pctAccountRisked,
        int? tradeGrade = null,
        int? executionGrade = null,
        int? MFEPips = null,
        int? MAEPips = null
        )
    {
        SqlCommand cmd = new SqlCommand("usp_InsertTrade");
        // required parameters
        cmd.Parameters.AddWithValue("@symbol", symbol);
        cmd.Parameters.AddWithValue("@tradeSetupId", tradeSetupId);
        cmd.Parameters.AddWithValue("@tradeTypeId", tradeTypeId);
        cmd.Parameters.AddWithValue("@lotsPerUnit", lotsPerUnit);
        cmd.Parameters.AddWithValue("@chartTimeFrame", chartTimeFrame);
        cmd.Parameters.AddWithValue("@pctAccountRisked", pctAccountRisked);

        // optional parameters
        if (MAEPips.HasValue)
            cmd.Parameters.AddWithValue("@MAEPips", MAEPips);
        if (MFEPips.HasValue)
            cmd.Parameters.AddWithValue("@MFEPips", MFEPips);
        if (tradeGrade.HasValue)
            cmd.Parameters.AddWithValue("@tradeGrade", tradeGrade);
        if (executionGrade.HasValue)
            cmd.Parameters.AddWithValue("@executionGrade", executionGrade);
        return (InsertData(cmd, "trade"));
    }

    public int InsertOrder(
        int tradeId,
        int units,
        string side,
        decimal price,
        decimal spread,
        int strategyId,
        string signalTypeId,
        int brokerId,
        string orderTypeId,
        DateTime orderDateTime,
        string comment,
        int? accountId = null
        )
    {
        SqlCommand cmd = new SqlCommand("usp_InsertOrder");
        // required parameters
        cmd.Parameters.Add(new SqlParameter("@tradeId", tradeId));
        cmd.Parameters.Add(new SqlParameter("@units", units));
        cmd.Parameters.Add(new SqlParameter("@side", side));
        cmd.Parameters.Add(new SqlParameter("@price", price));
        cmd.Parameters.Add(new SqlParameter("@spread", spread));
        cmd.Parameters.Add(new SqlParameter("@strategyId", strategyId));
        cmd.Parameters.Add(new SqlParameter("@signalTypeId", signalTypeId));
        cmd.Parameters.Add(new SqlParameter("@brokerId", brokerId));            
        cmd.Parameters.Add(new SqlParameter("@orderTypeId", orderTypeId));
        cmd.Parameters.Add(new SqlParameter("@orderDateTime", orderDateTime));
        cmd.Parameters.Add(new SqlParameter("@comment", comment));

        // optional parameters
        if (accountId.HasValue)
            cmd.Parameters.Add(new SqlParameter("@accountId", accountId));
        return (InsertData(cmd, "order"));
    } 

    private int InsertData(SqlCommand cmd, string tableName)
    {
        SqlConnection con = new SqlConnection(_connectionString);
        cmd.Connection = con;
        cmd.CommandType = CommandType.StoredProcedure;
        int rc = -1;
        try
        {
            con.Open();
            rc = (int) cmd.ExecuteScalar();
        }
        finally
        {
            con.Close();

        }
        return rc;
    }        
}

Я получаю доступ к этому коду со своей страницы ASP.NET следующим образом:

int tradeId = DB.InsertTrade (
    ddlSymbols.SelectedValue,
    ddlTradeSetups.SelectedValue, 
    int.Parse(ddlTradeTypes.SelectedValue), 
    decimal.Parse(txtLotsPerUnit.Text),
    ddlTimeFrames.Text,
    decimal.Parse(txtAcctRisk.Text));

int orderId = DB.InsertOrder (
    tradeId,
    int.Parse(txtUnits.Text),
    radSide.SelectedValue,
    Decimal.Parse(txtEntryPrice.Text),
    Decimal.Parse(txtSpread.Text),
    int.Parse(ddlStrategies.SelectedValue),
    "IE",
    int.Parse(ddlBrokers.SelectedValue),
    radSide.SelectedValue + radOrderType.SelectedValue,
    DateTime.Parse(txtEntryDate.Text + " " + txtEntryTime.Text),
    txtEntryComments.Text,
    int.Parse(ddlAccounts.SelectedValue));

То, что я хочу сделать, - это обернуть вызовы со страницы ASP.NET в SqlTransaction. Каков наилучший способ сделать это? Придется ли мне несколько реорганизовать мой код?

Большое спасибо.

Ответы [ 3 ]

4 голосов
/ 08 ноября 2010

Используйте объект TransactionScope для помещения нескольких операторов в одну транзакцию:

using (TransactionScope scope = new TransactionScope())
{
    // Database call 1 - within transaction
    // Database call 2 - within same transaction

    scope.Complete(); // Commit the transaction, or face an automatic rollback
}
0 голосов
/ 08 ноября 2010

Или используя класс SqlTransaction:

public void RunAsTransaction(string myConnString) 
{

SqlConnection myConnection = new SqlConnection(myConnString);
myConnection.Open();

SqlCommand myCommand = myConnection.CreateCommand();
SqlTransaction myTrans;

myTrans = myConnection.BeginTransaction();

myCommand.Connection = myConnection;
myCommand.Transaction = myTrans;

try
{
  myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
  myCommand.ExecuteNonQuery();
  myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
  myCommand.ExecuteNonQuery();
  myTrans.Commit();
  }
catch(Exception e)
{
  myTrans.Rollback();
}  
finally 
{
  myConnection.Close();
}

}

0 голосов
/ 08 ноября 2010

То, как вы вставляете новые данные в свое приложение, не сохраняет транзакции.Вы должны рефакторинг вашего кода все это в рамках одной транзакции и, возможно, соединения.

Быстрое и грязное исправление, которое заключается в создании соединения, открытии транзакции и передаче соединения каждому методу, вместо создания новых соединений внутри методов ... После того, как все методы вызываются и исключений / ошибок не былоуказал совершить транзакцию, в противном случае откат это.

Я предполагаю, что t будет сложно, но я бы рассмотрел использование некоторых ORM-преобразователей, таких как nHibernate.Зрелые картографы могут обрабатывать множество различных сценариев, включая ваш.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...