C#中的SQL - 为什么这么详细?

时间:2011-07-29 09:44:44

标签: c# sql

我在PHP中使用了postgreSQL,这很简单:当你进行查询时,你会这样做:

$result = pg_query($conn, "SELECT author, email FROM authors WHERE dest='" + pg_escape_string($s) + "'");

简单。安全(据我所知)。

现在我想在C#中用SQLite做同样的事情:

SQLiteCommand query = m_conn.CreateCommand();
query.CommandText = "SELECT author, email FROM authors WHERE dest=@param";
query.Parameters.Add("@dest", SqlDbType.String).Value = s;
m_datareader = query.ExecuteReader();

是不是有点矫枉过正?如果没有,为什么?

据我所知,最后,发送到数据库的字符串仍然是一个字符串,为什么要通过这个而不是仅手动清理不安全的字符串?如果在ASP .NET中将一些不安全的文本打印到HTML,那么它也是

htmlAdd.Text("<div>@param1</div>");
htmlAdd.Parameters.Add("@param1").Value = unsafeUsername;

我想做这个课程:

class QueryResultSet
{
    public QueryResultSet(SQLiteConnection conn, string queryText)
    {
        m_conn = conn;
        m_conn.Open();
        SQLiteCommand query = m_conn.CreateCommand();
        query.CommandText = queryText;
        m_datareader = query.ExecuteReader();
    }
    public object this[string key]
    {
        get { return m_datareader[key]; }
    }
    public bool Read()
    {
        return m_datareader.Read();
    }
    ~QueryResultSet()
    {
        m_conn.Close();
    }
    private SQLiteConnection m_conn;
    private SQLiteDataReader m_datareader;
}

但现在我必须改变方法:

public QueryResultSet(SQLiteConnection conn, string queryText, Dictionary<string,string> params)

这将导致方法之前的代码并使其大小加倍。

有任何标准方法吗?如果这个类不是一个好主意,那么如何避免为每个请求做10行呢?

6 个答案:

答案 0 :(得分:7)

参数化查询是更好的选择,因为它们通常是类型安全的,为您处理任何转义,文字格式等,以及允许服务器/后端缓存已编译的查询以获得更好的性能。

大多数数据库引擎都允许您同时执行“普通旧sql”和参数化查询。

当然,构建完整的SQL字符串需要您了解RDBMS使用的确切格式和数据类型,因为它们各不相同。

答案 1 :(得分:2)

有一些非常有效的工具可以帮助解决这个问题。既然你有SQL并且不需要复杂性,那么像“小巧”这样的微型ORM是一个合理的选择:

var result=conn.Query<Author>("SELECT author, email FROM authors WHERE dest=@s",
    new {s});

或者如果您想使用dynamic而不是强类型:

var result=conn.Query("SELECT author, email FROM authors WHERE dest=@s",new {s});

现在还不错吗?然后你可以通过以下方式消费它:

foreach(var obj in result) {
    Console.WriteLine("{0}: {1}", obj.Author, obj.Email");
}

答案 2 :(得分:2)

我使用扩展方法

public static IDataReader GetReader(this IDbConnection conn,string query, params object[] values) {
  var Command=conn.CreateCommand();
  var paramNames=Enumerable.Range(1,values.Length).Select(i=>string.Format("@param{0}",i)).ToArray();
  Command.CommandText=string.Format(query,paramNames);
  for (var i=0;i<values.Length;i++) {
    var param=Command.CreateParameter();
    param.ParameterName=paramNames[i];
    param.Value=values[i];
    Command.Parameters.Add(param);
  }
  return Command.ExecuteReader();
}

然后您可以在代码中使用字符串格式语法进行查询。

e.g。

Conn.GetReader("SELECT author, email FROM authors WHERE dest={0}",dest);

答案 3 :(得分:1)

获取和ORM或抽象此样板代码:

public static IDataReader ExecuteCommand(this IDbConnection dbConnection, 
    string query, object parameters)
{
    // Left as an exercise
}

var dataReader = connection.ExecuteCommand(
    "select * from Foo where Bar = @bar and Baz = @baz",
    new { bar = "12332", baz = DateTime.Now });

答案 4 :(得分:0)

如果你看一下C#(Linq to SQLEntity Framework)的标准ORM框架,你最终可能会得到这样的结论:

using (DBClasses db = new DBClasses())
{
    IEnumerable<AuthorInfo> authors = from item in db.authors
                                      where item.dest == s
                                      select item;
}

此代码以强类型方式提取作者,您不必自己输入SQL查询,也不必管理连接/ SQL读取器。

处理数据库“老派”方式只有在您需要高性能时才有道理。

答案 5 :(得分:0)

如果需要,您可以编写纯SQL:

SQLiteCommand query = m_conn.CreateCommand();
query.CommandText = "SELECT author, email FROM authors WHERE dest='" + s + "'";
m_datareader = query.ExecuteReader();

我通常会加上这个:

DataTable T = query.ExecuteReader().Tables[0];

因为DataTable对我来说比DataReader更有用。在成功的查询中,您始终可以获得一个数据表结果。