我应该将事务与命令ExecuteNonQuery一起使用吗



我在C#事务中使用ExecuteNonQuery调用了一些存储过程(postgresql中的函数(,我的SP看起来像

CREATE OR REPLACE FUNCTION public.setuserstatus(
par_userid integer,
par_status character varying)
RETURNS void
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
AS $BODY$
BEGIN
UPDATE public.user
SET status = par_status
WHERE userid = par_userid;
END;
$BODY$;

那么,调用此函数的最佳实践应该是什么呢?下面的代码足够了吗?或者我应该在事务内部使用这个并使用提交和回滚?请建议?

using (var conn = new NpgsqlConnection(_connectionString))
{
await conn.OpenAsync(ct);
using (var cmd = new NpgsqlCommand("irnutil.setcrdsstatusforapmaccount", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue(ApmAccountIdParameterName, accountId);
cmd.Parameters.AddWithValue(CrdsStatusParameterName, crdsStatus.ToString());
await cmd.ExecuteNonQueryAsync(ct);
}
}

此外,Npgsql文档说";但是,为了实现最大的可移植性,建议在命令上设置事务&";,这意味着我们应该在这里使用transaction吗?https://www.npgsql.org/doc/transactions.html

这取决于您想要实现的目标。

事务的一般概念是-针对数据库执行的工作单元

但是,您不希望在选择查询上使用事务。

例如:

select * from some table where condition = {condition}

不会成为适当交易区块的候选者。

您的更新示例是一个很好的候选者

现在的问题是,我应该在代码级别还是数据库级别使用它

答案又是一个问题——你想实现什么?


  • 如果在数据库级别执行该操作,您将失去记录错误的能力。是,交易,如果执行正确以满足您的条件将回滚操作,但您没有进一步的详细信息,这意味着您必须使用探查器确定失败的原因。另一方面,您的交易将是安全的,不受"外界"的影响-如果有机会发生,有人更改了您的代码,或者正在进行有害攻击地方,他们将无法更改事务和数据会更安全
  • 如果您在代码级别执行它,您将能够记录异常并查看失败原因,这将更容易但是以程序方式处理-它将暴露在代码更改中以及我上面提到的可能的恶意软件攻击
  • 在执行事务的过程中可能会出现死锁情况,这意味着如果执行事务中封装的sql块,则在事务完成其作业之前无法再次执行它,或者会遇到死锁并引发异常。在这种情况下,建议创建一个队列来监视对事务的调用,并检查是否可以再次执行

再说一遍,这都是您根据自己的需要做出的决定。

最新更新