适合c#应用的参数化查询类- sql server
本文关键字:sql server 查询 应用 参数 适合 | 更新日期: 2023-09-27 17:49:38
我开始将我的查询封装在单个参数化查询类
现在你可以评估我的类的性能安全性和其他所有可能的方面吗?
你有什么建议吗
这里是select class
public static DataSet cmd_SelectQuery(string srCommandText, List<string> lstParameterNames, List<string> lstParameters)
{
DataSet dsCmdPara = new DataSet();
try
{
using (SqlConnection connection = new SqlConnection(DbConnection.srConnectionString))
{
using (SqlCommand cmd = new SqlCommand(srCommandText, connection))
{
cmd.CommandType = CommandType.Text;
for (int i = 0; i < lstParameterNames.Count; i++)
{
cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i]);
}
connection.Open();
using (SqlDataAdapter sqlDa = new SqlDataAdapter(cmd))
{
sqlDa.Fill(dsCmdPara);
return dsCmdPara;
}
}
}
}
catch (Exception E)
{
csPublicFunctions.insertIntoTblSqlErrors(srCommandText + " " + E.Message.ToString());
}
return dsCmdPara;
}
这里是我的更新,删除类
public static void cmd_UpdateDeleteQuery(string srCommandText, List<string> lstParameterNames, List<string> lstParameters)
{
try
{
using (SqlConnection connection = new SqlConnection(DbConnection.srConnectionString))
{
using (SqlCommand cmd = new SqlCommand(srCommandText, connection))
{
cmd.CommandType = CommandType.Text;
for (int i = 0; i < lstParameterNames.Count; i++)
{
cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i]);
}
connection.Open();
cmd.ExecuteNonQuery();
}
}
}
catch (Exception E)
{
csPublicFunctions.insertIntoTblSqlErrors(srCommandText + " " + E.Message.ToString());
}
}
谢谢你的回答
由于我是在手机上写这篇文章,所以有两个快速的建议。
- 接收对象,而不是字符串
- 将params object[]作为参数列表可能会使你的方法使用起来更自然。
代码是有效且正确的。你要求反馈,所以我有以下几点:
(1)在构建参数的代码中,最好指定数据类型。
for (int i = 0; i < lstParameterNames.Count; i++)
{
var parameter = cmd.Parameters.AddWithValue(lstParameterNames[i], lstParameters[i]);
parameter.SqlDbType = SqlDbType.NVarChar; // or whatever type you need
}
(2)你不需要显式地打开/关闭连接,因为Fill方法已经为你完成了。
connection.Open();
using (SqlDataAdapter sqlDa = new SqlDataAdapter(cmd))
{
sqlDa.Fill(dsCmdPara);
connection.Close();
return dsCmdPara;
}
(3)如果你只打算有一个表,使用DataTable而不是DataSet。它会更快,更简单。
(4)这更像是一个风格点,但我发现显式关闭连接非常有帮助。如果结束语中有一个异常,有行号(通过pdb)是非常有用的。此外,它还有助于确保在忘记using时不会泄漏连接。
编辑
我想澄清第4点。假设当连接关闭时,清理导致了异常。如果不显式关闭连接,则会在Dispose方法中引发异常,该方法可能正在执行一堆其他工作。这使得很难看到我做了什么导致了问题。
看这个简单的例子。有一个底层资源需要清理(Dispose的全部原因),它会抛出一个异常。
public class Resource: IDisposable
{
public void Close()
{
CleanupMemory();
}
private void CleanupMemory()
{
throw new Exception();
}
public void Dispose()
{
CleanupMemory();
}
}
两种不同方法的(清理后的)堆栈跟踪如下:
using (var r = new Resource())
{
r.Close();
}
at ConsoleApplication1.Resource.CleanupMemory() in Program.cs:line 31
at ConsoleApplication1.Resource.Close() in Program.cs:line 26
at ConsoleApplication1.Program.Main(String[] args) Program.cs:line 16
和
using (var r = new Resource())
{
}
at ConsoleApplication1.Resource.CleanupMemory() in Program.cs:line 35
at ConsoleApplication1.Resource.Dispose() in Program.cs:line 40
at ConsoleApplication1.Program.Main(String[] args) in Program.cs:line 18
在第一个例子中,我知道我调用Close导致了异常,我有一个地方开始调试。如果只知道抛出了异常,则需要完全依赖异常中的信息。我没有其他的背景了。而且大多数异常消息都不是特别清楚。:)
都是完全正确的,只是不同而已。
埃里克
public DataTable Get_DTable(String Query, Dictionary<String, String> Parameters)
{
try
{
using (con = new SqlConnection(cls_Connection.URL()))
{
if (con.State == 0)
con.Open();
using (cmd = new SqlCommand(Query, con))
{
foreach (KeyValuePair<string, string> item in Parameters)
{
cmd.Parameters.AddWithValue(item.Key, item.Value);
}
using (da = new SqlDataAdapter(cmd))
{
using (dt = new DataTable())
{
da.Fill(dt);
if (dt.Rows.Count > 0)
{
return dt;
}
}
}
}
}
}
catch (Exception exp)
{
MessageBox.Show(exp.Message,
"Information",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
return null;
}