gpt4 book ai didi

c# - 在事务中调用多个 SQL Server 存储过程

转载 作者:可可西里 更新时间:2023-11-01 08:03:47 25 4
gpt4 key购买 nike

为了在我当前的项目中使用,我创建了一个允许我调用 SQL Server 异步的类。

我的代码是这样的:

internal class CommandAndCallback<TCallback, TError>
{
public SqlCommand Sql { get; set; }
public TCallback Callback { get; set; }
public TError Error { get; set; }
}

class MyCodes:SingletonBase<MyCodes>
{
private static string _connString = @"Data Source=MyDB;Initial Catalog=ED;Integrated Security=True;Asynchronous Processing=true;Connection Timeout=0;Application Name=TEST";

private MyCodes() { }

public void SetSystem(bool production)
{
_connString =
string.Format(@"Data Source=MyDB;Initial Catalog={0};Integrated Security=True;Asynchronous Processing=true;Connection Timeout=0;Application Name=TEST", production ? "ED" : "TEST_ED");
}

public void Add(string newCode, Action<int> callback, Action<string> error)
{
var conn = new SqlConnection(_connString);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = @"ADD_CODE";
cmd.Parameters.Add("@NEW", SqlDbType.NVarChar).Value = newCode;
cmd.Parameters.Add("@NewId", SqlDbType.Int).Direction = ParameterDirection.Output;

try
{
cmd.Connection.Open();
}
catch (Exception ex)
{
error(ex.ToString());
return;
}

var ar = new CommandAndCallback<Action<int>, Action<string>> { Callback = callback, Error = error, Sql = cmd };
cmd.BeginExecuteReader(Add_Handler, ar, CommandBehavior.CloseConnection);
}

private static void Add_Handler(IAsyncResult result)
{
var ar = (CommandAndCallback<Action<int>, Action<string>>)result.AsyncState;
if (result.IsCompleted)
{
try
{
ar.Sql.EndExecuteReader(result);
ar.Callback(Convert.ToInt32(ar.Sql.Parameters["@NewId"].Value));
}
catch (Exception ex)
{
ar.Error(ex.Message);
}
}
else
{
ar.Error("Error executing SQL");
}
}

public void Update(int codeId, string newCode, Action callback, Action<string> error)
{
var conn = new SqlConnection(_connString);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandTimeout = 0;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = @"UPDATE_CODE";
cmd.Parameters.Add("@CODE_ID", SqlDbType.Int).Value = codeId;
cmd.Parameters.Add("@NEW", SqlDbType.NVarChar).Value = newCode;

try
{
cmd.Connection.Open();
}
catch (Exception ex)
{
error(ex.ToString());
return;
}

var ar = new CommandAndCallback<Action, Action<string>> { Callback = callback, Error = error, Sql = cmd };
cmd.BeginExecuteReader(Update_Handler, ar, CommandBehavior.CloseConnection);
}

private static void Update_Handler(IAsyncResult result)
{
var ar = (CommandAndCallback<Action, Action<string>>)result.AsyncState;
if (result.IsCompleted)
{
try
{
ar.Sql.EndExecuteReader(result);
ar.Callback();
}
catch (Exception ex)
{
ar.Error(ex.Message);
}
}
else
{
ar.Error("Error executing SQL");
}
}

}

这可能看起来像太多的代码,但它让我可以这样调用它:

private void Add_Click(object sender, EventArgs e)
{
MyCodes.Instance.Add("Test",Success,Error)
}

private void Success(int newId)
{
MessageBox.Show(newId.ToString(), "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

private void Error(string error)
{
MessageBox.Show(error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

上面的代码对我来说工作得很好,我能够异步执行每个调用。

我现在遇到的问题是作为交易进行多次调用 - 我想更新 2 个代码并添加一个新代码。

通常我会调用更新,然后在成功的处理程序中调用第二次更新,在第二次更新的处理程序中我会调用返回新 ID 的添加。

类似于:

-UPDATE CODE
|-UPDATE CODE
|-ADD CODE (only this one return something)

但我想将所有这些称为事务,因此如果添加代码会中断,更新会回滚。

问题:

是否可以将多个异步查询作为事务调用?

我可以将上述方法作为事务调用,还是必须创建单独的方法来将我的过程作为一个调用? (我想避免这个,因为它只是将相同的代码从一种方法复制到另一种方法)

我想补充一点,我使用的是 .NET 3.5,所以 await 和其他不错的功能不是一个选项。

最佳答案

  string cnnString =WebConfigurationManager.ConnectionStrings["MyString"].ConnectionString;
SqlConnection cnn = new SqlConnection(cnnString);
SqlTransaction transaction;

cnn.Open();
transaction = cnn.BeginTransaction();

try
{

// Command Objects for the transaction
SqlCommand cmd1 = new SqlCommand("sproc1", cnn);
SqlCommand cmd2 = new SqlCommand("sproc2", cnn);

cmd1.CommandType = CommandType.StoredProcedure;
cmd2.CommandType = CommandType.StoredProcedure;

cmd1.Parameters.Add(new SqlParameter("@Param1", SqlDbType.NVarChar, 50));
cmd1.Parameters["@Param1"].Value = paramValue1;

cmd1.Parameters.Add(new SqlParameter("@Param2", SqlDbType.NVarChar, 50));
cmd1.Parameters["@Param2"].Value = paramValue2;

cmd2.Parameters.Add(new SqlParameter("@Param3", SqlDbType.NVarChar, 50));
cmd2.Parameters["@Param3"].Value = paramValue3;

cmd2.Parameters.Add(new SqlParameter("@Param4", SqlDbType.NVarChar, 50));
cmd2.Parameters["@Param4"].Value = paramValue4;

cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();

transaction.Commit();
}

catch (SqlException sqlEx)
{
transaction.Rollback();
}

finally
{
cnn.Close();
cnn.Dispose();
}

关于c# - 在事务中调用多个 SQL Server 存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15431285/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com