【发布时间】:2018-03-16 23:46:08
【问题描述】:
我继承了一些与 GP 接口的代码。在调试问题之前查看代码时,我发现了一个撤消对一组表的更新的函数。
该代码包含许多 SQL 命令,我想知道与在每一行上运行所有这些命令相比,我是否会从具有输入参数表 ds 的单个存储过程中获得更好的性能单独的表。
private void revertSave()
{
try
{
SqlConnection conn = GetConnectionToGP();
if (conn != null)
{
using (SqlCommand cmd = new SqlCommand())
{
//records from InventoryTransaction Master, Detail, and Serial tables when window is opened.
foreach (DataRow dr in _ds.Tables[0].Rows)
{
cmd.Connection = conn;
//TRANSACTION tables
cmd.CommandText = "UPDATE InventoryTransaction_Master " +
"SET Completed = 0 WHERE DocumentNumber = " + SqlString(dr["DocumentNumber"].ToString().Trim());
cmd.ExecuteNonQuery();
cmd.CommandText = "UPDATE InventoryTransaction_Serial " +
"SET BIN = '' " +
"WHERE DocumentNumber = " + SqlString(dr["DocumentNumber"].ToString().Trim()) +
" and DocumentType = 1 and ItemNumber = " + SqlString(dr["PrefixedItemNumber"].ToString().Trim()) +
" and LineSequenceNumber = " + SqlString(dr["LineSequenceNumber"].ToString().Trim()) +
" and SerialNumber = " + SqlString(dr["SerialNumber"].ToString().Trim());
cmd.ExecuteNonQuery();
//TRANSFER tables
cmd.CommandText = "SELECT DISTINCT detail.DocumentNumber " +
"FROM InventoryTransfer_Detail detail " +
"INNER JOIN InventoryTransfer_Serial serial ON detail.DocumentNumber = serial.DocumentNumber " +
"and detail.ItemNumber = serial.ItemNumber " +
"and detail.LineSequenceNumber = serial.LineSequenceNumber " +
"WHERE SessionID = " + SqlString(dr["SessionID"].ToString().Trim()) +
" and SerialNumber = " + SqlString(dr["SerialNumber"].ToString().Trim());
object obj = cmd.ExecuteScalar();
if (obj != null)
{
cmd.CommandText = "UPDATE InventoryTransfer_Master " +
"SET Completed = 0 WHERE DocumentNumber = " + SqlString(obj.ToString());
cmd.ExecuteNonQuery();
cmd.CommandText = "UPDATE InventoryTransfer_Serial " +
"SET OriginalBin = '', NewBin = '' " +
"WHERE DocumentNumber = " + SqlString(obj.ToString()) + " and SerialNumber = " + SqlString(dr["SerialNumber"].ToString().Trim());
cmd.ExecuteNonQuery();
}
}
}
if (conn.State == ConnectionState.Open)
conn.Close();
}
//this.Close();
}
catch (Exception ex)
{
ELog el = new ELog(ex, CLASS_NAME + " revertSave");
}
}
【问题讨论】:
-
对代码的最大担忧是 SQL 注入,但这并不意味着存储过程就是答案。参数是一个单独的主题。
-
“显示的代码”和“存储过程”之间存在错误的二分法;您可以使用正确参数化的命令获得存储过程的所有相同性能特征,注意单个
CommandText仍然可以执行多个TSQL 操作;关于该主题的一些冗长阅读:blog.marcgravell.com/2017/12/… -
@MarcGravell 它是在防火墙后面的终端服务器中运行的应用程序,而不是 Web 应用程序。
-
除了完全参数化的存储过程或批处理之外,您可能还希望将语句包含在事务中以确保全或无。由于更少的日志记录,这也将提高性能。
-
@pacmaninbw 这不会改变我说的一件事:) 如果您认为 SQL 注入不适用于内部系统,那么……您需要重新考虑这一点;除此之外,我所说的关于性能的一切都适用于无论你的 SQL 注入方法
标签: c# sql sql-server performance stored-procedures