简体   繁体   English

重复的SQL连接,我应该创建一个类吗?

[英]Repeated SQL Connections, should I create a class?

I'm still quite new to c# and I have multiple count queries on a single page. 我对C#还是很陌生,并且在一个页面上有多个计数查询。 I don't need to use these queries anywhere else so have avoided creating a class. 我不需要在其他任何地方使用这些查询,因此避免了创建一个类。 Still though, I can help but think there must be a more efficient approach but I was wondering what that would be! 尽管如此,我可以帮忙,但认为必须有一个更有效的方法,但是我想知道那会是什么!

Here's an example 这是一个例子

    private void cntUp() {
    Dictionary<string, string> crd = getCredentials(Session["secure"].ToString());
    Label UserUpcoming = frmDash.FindControl("lblUserReviewUp") as Label;

    using (SqlConnection con = new SqlConnection(WebConfigurationManager.ConnectionStrings["CS"].ConnectionString))
    {
        con.Open();
        try
        {
            using (SqlCommand countUpcoming = new SqlCommand("SELECT COUNT(*) FROM vw_dash_user_upcoming WHERE Employee_ID = @employee_id", con))
            {
                countUpcoming.Parameters.Add(new SqlParameter("employee_id",     crd["employee_id"].ToString()));
                SqlDataReader readerUpcoming = countUpcoming.ExecuteReader();
                while (readerUpcoming.Read())
                {
                    UserUpcoming.Text = readerUpcoming.GetInt32(0).ToString();
                }
            }
            con.Close();
        }
        catch
        {
            Response.Redirect(this.ErrorPage);
        }
    }
}

The following Repository works with SQL Server. 以下存储库可用于SQL Server。

Basically, you can either issue a regular or parameterized query. 基本上,您可以发出常规查询或参数化查询。 You can pass in your parameters as all strings, or just as objects if you are going to use models with strongly typed numbers and dates. 您可以将参数作为所有字符串传递,也可以作为对象传递(如果要使用具有强类型数字和日期的模型)。

You can take out the Release mode info if you don't use such a construct in developement, this is just to make it easier to switch between development and production databases without coding a change. 如果在开发中不使用这样的构造,则可以获取发布模式信息,这只是为了更轻松地在开发和生产数据库之间进行切换而无需编写更改。

An example usage would be : 一个示例用法是:

      var updateStatement = "UPDATE OCCHistoryHeaders SET ValidatingUsername=@pUsername,ValidatingWorkstation=@pWorkstation,CurrentState = @pCurrentStatus,RejectionReason = @pRejectionReason, AutomatedValidation = '0' WHERE BatchId = @pBatchId";

                var parameters = new Dictionary<string, object>
                    {
                        {"pUsername", Environment.UserName},
                        {"pWorkstation", Environment.MachineName},
                        {"pCurrentStatus", currentStatus},
                        {"pRejectionReason", rejectionReason},
                        {"pBatchId", batchId}
                    };

var absRowsUpdated = _occDb.ExecuteParameterizedNonQueryObjects(updateStatement, parameters);

Here is the class... 这是课程...

public class SomeRepository 
        {
            private  string _connectionString { get; set; }
            private  SqlConnection _sqlConnection { get; set; }

            public SomeRepository()
            {
                switch (AppSettings.ReleaseMode)
                {
                    case ReleaseMode.DEV:
                        _connectionString = "server=;database=;User Id=;Password=";
                        break;
                    case ReleaseMode.PRODUCTION:
                        _connectionString = "server=;database=;User Id=;Password=";
                        break;
                }            
            }     

            public  DataTable ExecuteQuery(string commandText)
            {
                var dataTable = new DataTable();
                var _sqlConnection = new SqlConnection(_connectionString);
                var cmd = new SqlCommand(commandText, _sqlConnection);
                var da = new SqlDataAdapter(cmd);

                try
                {              
                    _sqlConnection.Open();
                    da.Fill(dataTable);                             
                }
                catch (Exception ex)
                {
                    var errorText = string.Format("Occ Repository ExecuteQuery Error : QueryString={0} :: Error={1}", commandText, ex.Message);
                    throw new Exception(errorText, ex);
                }
                finally
                {                
                    da.Dispose();
                    _sqlConnection.Dispose();
                }

                return dataTable;
            }

            public DataTable ExecuteParameterizedQuery(string commandText, Dictionary<string, string> parameters)
            {
                var dataTable = new DataTable();
                var _sqlConnection = new SqlConnection(_connectionString);
                var cmd = new SqlCommand(commandText, _sqlConnection);

                var da = new SqlDataAdapter(cmd);
                foreach (var entry in parameters)
                {
                    cmd.Parameters.Add(entry.Key, entry.Value);
                }

                try
                {
                    _sqlConnection.Open();
                    da.Fill(dataTable);
                }
                catch (Exception ex)
                {
                    var errorText = string.Format("Occ Repository ExecuteQuery Error : QueryString={0} :: Error={1}", commandText, ex.Message);
                    throw new Exception(errorText, ex);
                }
                finally
                {
                    da.Dispose();
                    _sqlConnection.Dispose();
                }

                return dataTable;
            }

            public DataTable ExecuteParameterizedQueryObjects(string commandText, Dictionary<string, object> parameters)
            {
                var dataTable = new DataTable();
                var _sqlConnection = new SqlConnection(_connectionString);
                var cmd = new SqlCommand(commandText, _sqlConnection);

                var da = new SqlDataAdapter(cmd);
                foreach (var entry in parameters)
                {
                    cmd.Parameters.Add(entry.Key, entry.Value);
                }

                try
                {
                    _sqlConnection.Open();
                    da.Fill(dataTable);
                }
                catch (Exception ex)
                {
                    var errorText = string.Format("Occ Repository ExecuteQuery Error : QueryString={0} :: Error={1}", commandText, ex.Message);
                    throw new Exception(errorText, ex);
                }
                finally
                {
                    da.Dispose();
                    _sqlConnection.Dispose();
                }

                return dataTable;
            }

            public int ExecuteNonQuery(string commandText)
            {          
                var _sqlConnection = new SqlConnection(_connectionString);
                var rowsAffected = 0;

                try
                {              
                    var cmd = new SqlCommand(commandText, _sqlConnection);
                    _sqlConnection.Open();
                    rowsAffected = cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    var errorText = string.Format("Occ Repository ExecuteNonQuery Error : Command={0} :: Error={1}", commandText, ex.Message);
                    throw new Exception(errorText, ex);
                }
                finally
                {
                    _sqlConnection.Dispose();
                }

                return rowsAffected;
            }

            public int ExecuteParameterizedNonQuery(string commandText, Dictionary<string, string> parameters)
            {
                var _sqlConnection = new SqlConnection(_connectionString);
                var rowsAffected = 0;
                var cmd = new SqlCommand(commandText, _sqlConnection);

                foreach (var entry in parameters)
                {
                    cmd.Parameters.Add(entry.Key, entry.Value);
                }

                try
                {               
                    _sqlConnection.Open();
                    rowsAffected = cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    var errorText = string.Format("Occ Repository ExecuteNonQuery Error : Command={0} :: Error={1}", commandText, ex.Message);
                    throw new Exception(errorText, ex);
                }
                finally
                {
                    _sqlConnection.Dispose();
                }

                return rowsAffected;
            }

            public int ExecuteParameterizedNonQueryObjects(string commandText, Dictionary<string, object> parameters)
            {
                var _sqlConnection = new SqlConnection(_connectionString);
                var rowsAffected = 0;
                var cmd = new SqlCommand(commandText, _sqlConnection);

                foreach (var entry in parameters)
                {
                    cmd.Parameters.Add(entry.Key, entry.Value);
                }

                try
                {
                    _sqlConnection.Open();
                    rowsAffected = cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    var errorText = string.Format("Occ Repository ExecuteNonQuery Error : Command={0} :: Error={1}", commandText, ex.Message);
                    throw new Exception(errorText, ex);
                }
                finally
                {
                    _sqlConnection.Dispose();
                }

                return rowsAffected;
            }

        }

If you only do stuff 1 place, generally you'd make everything less readable. 如果只在1个地方放东西,通常会使所有内容的可读性降低。 So I would probably avoid it. 所以我可能会避免。 It's a common pattern, however, to you would do yourself a favor writing a utility class with some functions for this. 但是,这是一种常见的模式,这对编写一个带有一些功能的实用程序类的人来说是一个帮忙。

//requires query parameters to have names @0, @1 etc in string
public static List<object[]> Query(String query, params String[] parameters) //no injection check on this string, be careful.
{
    using(SqlConnection conn = new SqlConnection(_CONN_STRING_))
    {
        conn.Open()
        using(SqlCommand cmd = new SqlCommand(query, conn))
        {
            AddSqlParams(cmd, parameters);
            return Query(cmd);
        }

    }
}

/// <summary>Generic SQL query. Requires open connection.</summary>
/// <param name="cmd">SqlCommand object with all necessary fields configured.</param>
/// <returns>A list of Object arrays (each array is one row).</returns>
private static List<Object[]> Query(SqlCommand cmd)
{
    List<Object[]> results = new List<Object[]>();
    using (SqlDataReader rdr = cmd.ExecuteReader())
    {
        while (rdr.Read())
        {
            Object[] row = new Object[rdr.VisibleFieldCount];
            rdr.GetValues(row);
            results.Add(row);
        }
        return results;
    }
}

private static void AddSqlParams(SqlCommand cmd, params String[] sqlParams)
{
    for (Int32 i = 0; i < sqlParams.Length; i++)
        cmd.Parameters.AddWithValue("@" + i, (Object)sqlParams[i] ?? DBNull.Value);
}

Then use like 然后使用像

UserUpcoming.Text = Query("SELECT COUNT(*) FROM vw_dash_user_upcoming WHERE Employee_ID = @0", crd["employee_id"].ToString())[0][0];

I like to have a separate class for each table in the database. 我喜欢为数据库中的每个表都有一个单独的类。 In your case I would have a separate class called vw_dash_user_upcoming, this would have a static method something like... 在您的情况下,我将有一个名为vw_dash_user_upcoming的单独的类,它将有一个类似于...的静态方法。

public static int CountEmployees(int employeeId) {
    int returnValue;
    // do database stuff here
    return returnValue;
}

I usually create a folder and namespace in my project called "database" and all the database stuff goes in there. 我通常在我的项目中创建一个名为“数据库”的文件夹和名称空间,所有数据库内容都放在其中。 Nothing goes in there that's not database access. 没有什么没有数据库访问权限。 For me this really helps keep things organized, especially in a large project. 对我来说,这确实有助于使事情井井有条,特别是在大型项目中。

Personally I would create a separate class, simply because it's not a good idea to keep pieces of code with totally different responsibilities in one class. 我个人将创建一个单独的类,只是因为将具有完全不同职责的代码片段保留在一个类中不是一个好主意。 When divided into small classes code is easier to read and maintain. 当分成小类时,代码更易于阅读和维护。

Communication with database should be separated anyway to make it easier to switch between datasources (eg different database servers). 无论如何,与数据库的通信都应该分开,以使其更容易在数据源之间进行切换(例如,不同的数据库服务器)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM