【问题标题】:c# Reducing the number of methods used to get data from a DBc#减少用于从数据库获取数据的方法数量
【发布时间】:2016-11-02 15:47:32
【问题描述】:

我有一个处理数据库列元数据的类。类的属性之一是有问题的表。这通过构造函数传递给对象。同样在构造函数中,我应用一些逻辑来分配类中的其他变量。为此,有许多私有方法可以连接到数据库,查询有关表的内容,并将值返回给变量。

我的问题是我有很多不同的方法做几乎相同的事情,但返回不同的数据类型。所以例如我的代码是这样的

public Column(string tableName)
{
   strTableName = tableName;
   pkColumnName = GetPKColumnName(tableName);
   pkColumnLenght = GetPKColumnLenght(tableName);
}

private string GetPKColumnName(string tableName)
{
   string query = String.Format("SELECT myColName FROM myTable where myTableName = {0}",  tableName);
   string result = "";
   try
   {
       using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString))
         {
          con.Open();
          using (SqlCommand command = new SqlCommand(query, con))
          {
             result = (string)command.ExecuteScalar();
          }
         }
    }
    catch (SqlException ex)
    {
         Console.WriteLine(ex.Message);
    }
 return result;
}

private int GetPKColumnLenght(string tableName)
    {
       string query = String.Format("SELECT myColLenght FROM myTable where myTableName = {0}",  tableName);
       int result = 0;
       try
       {
           using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString))
             {
              con.Open();
              using (SqlCommand command = new SqlCommand(query, con))
              {
                 result = (int)command.ExecuteScalar();
              }
             }
        }
        catch (SqlException ex)
        {
             Console.WriteLine(ex.Message);
        }
     return result;
    }

还有很多其他类似的方法。这对我来说看起来不太好,所以我想知道这样的最佳实践是什么。

我是否应该将返回类型声明为对象并在将返回值分配给我的变量时进行数据类型转换?

【问题讨论】:

标签: c# methods code-reuse


【解决方案1】:

我的答案和其他人假设不同的问题。在我看来,您正在尝试从特定列中查询单个值,并且您必须创建一个新方法,因为类型不同。也就是说,我个人只会使用一个简单的 ORM 解决方案,而另一个答案当然没有错,只是另一个抽象。

您将需要使用泛型并转换为泛型。

我没有测试过这段代码,它更像是一个指南。

private T GetValue<T>(string tableName, colName)
{
   string query = String.Format("SELECT {0} FROM myTable where myTableName = {1}", colName, tableName);
   T result = default(T);
   try
   {
       using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString))
         {
          con.Open();
          using (SqlCommand command = new SqlCommand(query, con))
          {
             result = (T)command.ExecuteScalar();
          }
         }
    }
    catch (SqlException ex)
    {
         Console.WriteLine(ex.Message);
    }
 return result;
}

【讨论】:

  • 好奇为什么投反对票,它简洁地回答了他提出的问题而没有做太多假设
  • 这对 SQL 注入是开放的——我希望应用程序只将常量传递给方法,但是在传递要注入的东西的地方构建动态 SQL 仍然会出现错误或恶意。除了将myTableName 参数固定为SQL 参数之外,无需大量额外工作(尽管会稍慢)的安全方法是执行select *,然后使用a 检索适当的值SqlDataReader.
  • 虽然肯定是真的,但您认为您认为它有一个用户界面吗?我没有读到任何相关的内容
  • UI 与否,拥有一种基于任意输入随意构建 SQL 的方法是一种糟糕的模式。否则,如果有人进来并编写了一些好的单元测试,或者如果它曾经被移植到确实有 UI 的东西上,那么你就会得到一段易受攻击的代码。另一个问题(可能可以通过添加方括号来解决)是 SQL 关键字(如 From)或多字列名将在此处失败。我认为方括号每次都能解决这个问题,但仍然需要考虑其他问题。
【解决方案2】:

创建SqlManager

public class SqlManager
{

    public static string ConnectionString
    {
        get
        {
            return "Your ConnectionString"
        }
    }

    public static SqlConnection GetSqlConnection(SqlCommand cmd)
    {
        if (cmd.Connection == null)
        {
            SqlConnection conn = new SqlConnection(ConnectionString);

            conn.Open();

            cmd.Connection = conn;

            return conn;
        }

        return cmd.Connection; 
    }

    public static object ExecuteScalar(SqlCommand cmd)
    {

        SqlConnection conn = GetSqlConnection(cmd);

        try
        {
            return cmd.ExecuteScalar();
        }
        catch
        {
           throw;
        }
        finally
        {
           conn.Close();
        }
   }

}

现在你的方法,第二个同样的事情:

private string GetPKColumnName(string tableName)
{
    string query = String.Format("",  tableName);

    SqlCommand cmd = new SqlCommand();
    cmd.CommandText = @"SELECT myColName FROM myTable where myTableName = @TableName";

    cmd.Parameters.AddWithValue("@TableName", tableName);

    object result = SqlManager.ExecuteScalar(cmd);

    return result != null ? (int)object: 0;
}

【讨论】:

    猜你喜欢
    • 2021-11-14
    • 2020-05-18
    • 1970-01-01
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 2019-09-25
    • 2013-01-22
    相关资源
    最近更新 更多