在C#中使用SqlCommand准备的优点和缺点?

Mad*_*Boy 35 c# sql-server performance

当我正在阅读书籍以学习C#(可能是一些Visual Studio 2005旧书)时,我遇到过SqlCommand.Prepare每次执行SQL调用时都会使用的建议(无论是'a SELECT/ UPDATEINSERTSQL SERVER 2005/2008),我都将参数传递给它.但它真的如此吗?

  1. 应该每次都这样吗?或者有时候?

  2. 它是一个参数传递还是五个或二十个是否重要?

  3. 如果有的话应该提供什么?它是否会引人注目(我一直在SqlCommand.Prepare这里使用并跳过它,从来没有任何问题或明显的差异).

为了问题,这是我使用的常用代码,但这更像是一个普遍的问题.

public static decimal pobierzBenchmarkKolejny(string varPortfelID, DateTime data, decimal varBenchmarkPoprzedni, decimal varStopaOdniesienia) {
    const string preparedCommand = @"SELECT [dbo].[ufn_BenchmarkKolejny](@varPortfelID, @data, @varBenchmarkPoprzedni,  @varStopaOdniesienia) AS 'Benchmark'";
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP)) //if (varConnection != null) {
    using (var sqlQuery = new SqlCommand(preparedCommand, varConnection)) {
        sqlQuery.Prepare();
        sqlQuery.Parameters.AddWithValue("@varPortfelID", varPortfelID);
        sqlQuery.Parameters.AddWithValue("@varStopaOdniesienia", varStopaOdniesienia);
        sqlQuery.Parameters.AddWithValue("@data", data);
        sqlQuery.Parameters.AddWithValue("@varBenchmarkPoprzedni", varBenchmarkPoprzedni);
        using (var sqlQueryResult = sqlQuery.ExecuteReader())
            if (sqlQueryResult != null) {
                while (sqlQueryResult.Read()) {

                }
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

补充说明:

如果我sqlQuery.Prepare()像下面的代码一样移动异常被抛出必须明确声明大小,这基本上让我认为sqlQuery.Prepare()首先使它无用吗?有人可以使用我的例子显示正确的用法吗?

public static decimal pobierzBenchmarkKolejny(string varPortfelID, DateTime data, decimal varBenchmarkPoprzedni, decimal varStopaOdniesienia) {
    const string preparedCommand = @"SELECT [dbo].[ufn_BenchmarkKolejny](@varPortfelID, @data, @varBenchmarkPoprzedni,  @varStopaOdniesienia) AS 'Benchmark'";
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP)) //if (varConnection != null) {
    using (var sqlQuery = new SqlCommand(preparedCommand, varConnection)) {

        sqlQuery.Parameters.AddWithValue("@varPortfelID", varPortfelID);
        sqlQuery.Parameters.AddWithValue("@varStopaOdniesienia", varStopaOdniesienia);
        sqlQuery.Parameters.AddWithValue("@data", data);
        sqlQuery.Parameters.AddWithValue("@varBenchmarkPoprzedni", varBenchmarkPoprzedni);
        sqlQuery.Prepare();
        using (var sqlQueryResult = sqlQuery.ExecuteReader())
            if (sqlQueryResult != null) {
                while (sqlQueryResult.Read()) {

                }
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

我该怎么办?通过在参数旁边添加.size并执行varPortfel.Lenght(如果它是字符串等)?

Ben*_*man 12

从MSDN文档:

"在调用Prepare之前,请在要准备的语句中指定每个参数的数据类型.对于具有可变长度数据类型的每个参数,必须将Size属性设置为所需的最大大小.如果满足这些条件,则准备返回错误不满足.

如果在调用Prepare之后调用Execute方法,则任何大于Size属性指定的值的参数值都将自动截断为参数的原始指定大小,并且不会返回截断错误.

输出参数(无论是否准备好)必须具有用户指定的数据类型.如果指定可变长度数据类型,则还必须指定最大大小."

此外,"如果CommandType属性设置为TableDirect,则Prepare不执行任何操作.如果CommandType设置为StoredProcedure,则对Prepare的调用应该成功,......"

这通常用于确保最终用户不使用SQL注入技术来添加或删除数据库中不需要的信息.

我查看了它并查看了这篇文章http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.prepare.aspx.您的问题是您需要在运行.Prepare()之前定义参数,然后在运行.Prepare()之后设置参数.现在你正在做两件事.我会尝试这样的事情(注意我没有测试它所以我的语法可能有点偏离).

public static decimal pobierzBenchmarkKolejny(string varPortfelID, DateTime data, decimal varBenchmarkPoprzedni, decimal varStopaOdniesienia) {
    const string preparedCommand = @"SELECT [dbo].[ufn_BenchmarkKolejny](@varPortfelID, @data, @varBenchmarkPoprzedni,  @varStopaOdniesienia) AS 'Benchmark'";
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP)) //if (varConnection != null) {
    using (var sqlQuery = new SqlCommand(preparedCommand, varConnection)) {

        sqlQuery.Parameters.Add("@varPortfelID");
        sqlQuery.Parameters.Add("@varStopaOdniesienia");
        sqlQuery.Parameters.Add("@data");
        sqlQuery.Parameters.Add("@varBenchmarkPoprzedni");

        sqlQuery.Prepare();
        sqlQuery.ExecuteNonQuery();//This might need to be ExecuteReader()

        sqlQuery.Parameters[0].Value = varPortfelID;
        sqlQuery.Parameters[1].Value = varStopaOdniesienia;
        sqlQuery.Parameters[2].Value = data;
        sqlQuery.Parameters[3].Value = varBenchmarkPoprzedni;

        using (var sqlQueryResult = sqlQuery.ExecuteReader())
            if (sqlQueryResult != null) {
                while (sqlQueryResult.Read()) {

                }
            }
    }
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*mes 6

另一个好处是,通过这样做,SQL查询计划被编译,缓存和重用.如果对查询的调用量很小,这不是什么大问题,但如果你有很多,那么这样做确实有一些显着的性能优势.

  • 你能添加任何支持链接吗? (3认同)