ADO.NET - 糟糕的做法?

时间:2010-03-02 18:21:35

标签: ado.net

我几个月前在MSDN上阅读了一篇文章,并且最近开始使用以下代码片段来执行ADO.NET代码,但我觉得它可能很糟糕。我是在反应还是完全可以接受?

private void Execute(Action<SqlConnection> action)
{
    SqlConnection conn = null;
    try {
        conn = new SqlConnection(ConnectionString);
        conn.Open();
        action.Invoke(conn);
    } finally {
        if (conn != null && conn.State == ConnectionState.Open) {
            try {
                conn.Close();
            } catch {
            }
        }
    }
}

public bool GetSomethingById() {
    SomeThing aSomething = null
    bool valid = false;
    Execute(conn =>
    {
        using (SqlCommand cmd = conn.CreateCommand()) {
            cmd.CommandText = ....
            ...
            SqlDataReader reader = cmd.ExecuteReader();
            ...
            aSomething = new SomeThing(Convert.ToString(reader["aDbField"]));
        }
    });
    return aSomething;
}

5 个答案:

答案 0 :(得分:8)

当你这样做时,有什么意义呢?

public SomeThing GetSomethingById(int id) 
{
    using (var con = new SqlConnection(ConnectionString)) 
    {
        con.Open();
        using (var cmd = con.CreateCommand()) 
        {
            // prepare command
            using (var rdr = cmd.ExecuteReader()) 
            {
                // read fields
                return new SomeThing(data);
            }
        } 
    }
}

您可以通过执行此类操作来促进代码重用。

public static void ExecuteToReader(string connectionString, string commandText, IEnumerable<KeyValuePair<string, object>> parameters, Action<IDataReader> action) 
{
    using (var con = new SqlConnection(connectionString)) 
    {
        con.Open();
        using (var cmd = con.CreateCommand()) 
        {
            cmd.CommandText = commandText;
            foreach (var pair in parameters) 
            {
                var parameter = cmd.CreateParameter();
                parameter.ParameterName = pair.Key; 
                parameter.Value = pair.Value; 
                cmd.Parameters.Add(parameter);
            }
            using (var rdr = cmd.ExecuteReader()) 
            {
                action(rdr);
            }
        } 
    }    
}

您可以像这样使用它:

//At the top create an alias
using DbParams = Dictionary<string, object>;

ExecuteToReader(
    connectionString, 
    commandText, 
    new DbParams() { { "key1", 1 }, { "key2", 2 } }),
    reader => 
    {
        // ...
        // No need to dispose
    }
)

答案 1 :(得分:1)

恕我直言,这确实是一种不好的做法,因为你正在为你执行的每个语句创建并打开一个新的数据库连接。

为什么不好:

  • 性能方面(虽然连接池有助于降低性能):您应该打开连接,执行必须执行的语句,并在不知道下一个语句何时将关闭时关闭连接执行。

  • 但肯定是在背景方面。我的意思是:你将如何处理交易?您的交易边界在哪里?您的应用程序层知道何时必须启动和提交事务,但是您无法使用这种工作方式将多个语句跨越到同一个sql-transaction中。

答案 2 :(得分:0)

这是可以接受的。我两年前创建了一个SqlUtilities类,它有类似的方法。如果你愿意,你可以更进一步。

编辑:无法找到代码,但我输入了一个小例子(可能有很多语法错误;)

<强> SQLUtilities

public delegate T CreateMethod<T> (SqlDataReader reader);
public static T CreateEntity<T>(string query, CreateMethod<T> createMethod, params SqlParameter[] parameters) {
   // Open the Sql connection
   // Create a Sql command with the query/sp and parameters
   SqlDataReader reader = cmd.ExecuteReader();
   return createMethod(reader);
   // Probably some finally statements or using-closures etc. etc.
} 

致电代码

private SomeThing Create(SqlDataReader reader) {
    SomeThing something = new SomeThing();
    something.ID = Convert.ToIn32(reader["ID"]);
    ...
    return something;
}

public SomeThing GetSomeThingByID (int id) {
    return SqlUtilities.CreateEntity<SomeThing> ("something_getbyid", Create, ....);
}

当然你可以使用lambda表达式而不是Create方法,你可以轻松地创建一个CreateCollection方法并重用现有的Create方法。

但是,如果这是一个新项目。查看实体的LINQ。比ADO.Net更容易和灵活。

答案 3 :(得分:0)

这是一种非常合理的使用方法。

通过将连接逻辑包装到采用Action<SqlConnection>的方法中,您可以帮助防止重复代码和引入错误的可能性。由于我们现在可以使用lambdas,这将成为处理这种情况的一种简单,安全的方法。

答案 4 :(得分:0)

嗯,在我看来,在完成它之前检查你做了什么。有效的东西并不意味着它是最好和最好的编程实践。查看并找到一个具体的例子和使用它的好处。但如果你是考虑使用大型项目​​,使用像NHibernate这样的框架会很好。因为有很多项目甚至是基于它开发的框架,比如http://www.cuyahoga-project.org/