首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单的SqlHelper,包装了ADO.NET方法

简单的SqlHelper,包装了ADO.NET方法
EN

Code Review用户
提问于 2014-09-21 14:16:52
回答 3查看 11.9K关注 0票数 4

我正在创建一个简单的SqlHelper,这将简化ADO.NET方法的使用。有谁能帮我复习一下这门课,看看有没有问题或遗漏了什么?

代码语言:javascript
复制
public static class SqlHelper
{
    public static async Task<int> ExecuteNonQueryAsync(string connectionString, CommandType cmdType, string cmdText,
        params SqlParameter[] commandParameters)
    {
        using (var connection = new SqlConnection(connectionString))
        {
            using (var command = new SqlCommand(cmdText, connection))
            {
                try
                {
                    command.CommandType = cmdType;
                    command.Parameters.AddRange(commandParameters);
                    connection.Open();
                    return await command.ExecuteNonQueryAsync();
                }
                finally
                {
                    connection.Close();
                }
            }
        }

    }


    public static async Task<SqlDataReader> ExecuteReaderAsync(string connectionString, CommandType cmdType,
        string cmdText, params SqlParameter[] commandParameters)
    {
        using (var connection = new SqlConnection(connectionString))
        {
            using (var command = new SqlCommand(cmdText, connection))
            {
                try
                {
                    command.CommandType = cmdType;
                    command.Parameters.AddRange(commandParameters);
                    connection.Open();
                    return await command.ExecuteReaderAsync();
                }
                finally
                {
                    connection.Close();
                }
            }
        }
    }

    public static async Task<object> ExecuteScalarAsync(string connectionString, CommandType cmdType, string cmdText,
        params SqlParameter[] commandParameters)
    {
        using (var connection = new SqlConnection(connectionString))
        {
            using (var command = new SqlCommand(cmdText, connection))
            {
                try
                {
                    command.CommandType = cmdType;
                    command.Parameters.AddRange(commandParameters);
                    connection.Open();
                    return await command.ExecuteScalarAsync();
                }
                finally
                {
                    connection.Close();
                }
            }
        }
    }

}
EN

回答 3

Code Review用户

发布于 2014-09-21 18:03:53

嵌套.

可以通过堆叠using块来减少嵌套,如下所示:

代码语言:javascript
复制
    using (var connection = new SqlConnection(connectionString))
    using (var command = new SqlCommand(cmdText, connection))
    {
        try
        {
            command.CommandType = cmdType;
            command.Parameters.AddRange(commandParameters);
            connection.Open();
            return await command.ExecuteNonQueryAsync();
        }
        finally
        {
            connection.Close();
        }
    }

我喜欢您对var的使用,以及您在using块中包装了IDisposable内容的事实。然而,这是过分的:

finally { connection.Close(); }

因为connection被包装在一个using块中,所以不管代码到达using作用域末尾的原因是什么,连接都将被干净地关闭和释放。换句话说,您还可以丢弃try块,进一步减少嵌套:

代码语言:javascript
复制
    using (var connection = new SqlConnection(connectionString))
    using (var command = new SqlCommand(cmdText, connection))
    {
        command.CommandType = cmdType;
        command.Parameters.AddRange(commandParameters);
        connection.Open();
        return await command.ExecuteNonQueryAsync();
    }

这是因为using块是用于.的语言快捷方式。一个try...finally块。

XxxxxHelper综合征

一个名为SqlHelper的静态类的问题是,随着时间的推移,它成为任何与SQL相关的东西的弃置地;它会长头发和触角,甚至在你注意到之前就会变得一团糟:"Helper“这个名字太模糊了,不可能产生任何清晰的焦点。

我建议将它重命名为类似于SqlCommandWrapper的东西,这样它就不太可能因与执行SqlCommand无关的事情而变得臃肿起来,但可能与SqlWhatever有很远的关系。

票数 8
EN

Code Review用户

发布于 2014-09-22 15:35:02

在以前编写了此类类之后,我建议使用以下签名进行额外的重载:

代码语言:javascript
复制
public static async Task<IEnumerable<T>> ExecuteReaderAsync(
    string connectionString, 
    CommandType cmdType,
    string cmdText,
    Func<IDataReader, T> transform), 
    params SqlParameter[] commandParameters)

使用此重载,您将迭代数据读取器返回的结果,并对每一行调用转换方法并将其存储在List中。完成后,将结果作为IEnumerable返回给调用方。

我的特定实现总是返回一个空的可枚举的,永远不为空的。你可以选择不这样做。(我更喜欢可预测性,并保证该方法永远不会返回null。)

这就避免了调用者不得不自己编写这种样板。他们只是简单地叫:

代码语言:javascript
复制
var foo = await SqlHelper.ExecuteReaderAsync(
    myConnectionString,
    CommandType.StoredProcedure,
    "GetTheFoos",
    r => new Foo { Id = r["foo"], Name = r["Name"] },
    ); // No parameters

除此之外,其他评论都很精彩。

票数 4
EN

Code Review用户

发布于 2014-09-21 18:05:02

我不认为必须使用每个命令重复连接字符串更简单。为什么不让SqlHelper成为一个非静态类,将连接字符串传递给构造函数,然后从您的方法中使用它呢?

类似地,我相信大多数命令都将使用CommandType.Text,所以这应该是默认的。不能与params一起使用可选参数,因此必须使用单独的重载。

我不确定ExecuteReaderAsync会不会起作用。返回的读取器不需要打开连接吗?

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/63480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档