3

ASP.NET4.0アプリケーション用のすべてのデータアクセスコードを含むクラスがあります。クラスには、データベースにデータを挿入する2つのメソッドがあります。これらの挿入をSqlTransactionに参加させ、挿入の1つが失敗した場合にトランザクションをロールバックしたいと思います。ただし、コーディング方法が原因で、その方法がわかりません。これが私のデータアクセスコードです:

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でラップすることです。これを行うための最良の方法は何ですか?コードをいくらかリファクタリングする必要がありますか?

どうもありがとう。

4

3 に答える 3

4

オブジェクトを使用して、TransactionScope1つのトランザクション内に複数のステートメントを配置します。

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
}
于 2010-11-08T13:58:29.477 に答える
0

アプリケーションに新しいデータを挿入する方法は、トランザクションの保存ではありません。同じトランザクション内およびおそらく接続内で、コードをすべてリファクタリングする必要があります。

そのための迅速で汚い修正は、メソッド内に新しい接続を作成するのではなく、接続を作成し、トランザクションを開き、すべてのメソッドに接続を渡すことです...すべてのメソッドが呼び出され、例外/エラーが表示されなかった後、トランザクションをコミットします。ロールバックします。

tは難しいと思いますが、nHibernateのようなORMマッパーの使用を検討します。成熟したマッパーは、あなたを含む多くの異なるシナリオを処理できます。

于 2010-11-08T14:10:55.410 に答える
0

または、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();
}

}

于 2010-11-08T14:50:17.487 に答える