我的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中。做这个的最好方式是什么?我是否需要在某种程度上重构我的代码?
非常感谢。
答案 0 :(得分:4)
使用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
}
答案 1 :(得分:0)
在应用程序中插入新数据的方式不是事务保存。 您应该在同一事务和可能的连接中重构您的代码。
快速而又脏的修复方法是创建连接,打开事务并将连接传递给每个方法,而不是在方法中创建新连接...调用所有方法并且未指示异常/错误提交交易,否则回滚。
我认为这很难,但我会考虑使用像nHibernate这样的ORM映射器。 成熟的地图制作者可以处理许多不同的场景,包括你的场景。
答案 2 :(得分: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();
}
}