如何使用 SQL 参数从 SQL Server 获取数据集
本文关键字:SQL 获取 数据集 Server 参数 何使用 | 更新日期: 2023-09-27 18:30:56
我正在从事C#项目,我是这项技术的新手。
我想从 SQL Server 2008 中读取一些数据,我编写了以下代码
public User select(string username, string password)
{
string connection = ConfigurationManager.ConnectionStrings["lawyersDBConnectionString"].ConnectionString.ToString();
string sql = string.Format("select * from users where userName = '{0}' and password = '{1}'", username, password);
SqlConnection con = new SqlConnection();
con.ConnectionString = connection;
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(sql, con);
User user = new User();
DataRow dr;
try
{
da.Fill(ds);
dr = ds.Tables[0].Rows[0];
user.Id = Convert.ToInt16(dr["userID"]);
user.FirstName = (string)dr["firstName"];
user.LastName = (string)dr["lastName"];
user.Email = (string)dr["email"];
user.Username = (string)dr["userName"];
user.Password = (string)dr["password"];
user.type = (string)dr["type"];
return user;
}
catch (Exception ex)
{
return null;
}
}//end of select method
但是我读过一篇关于SQL注入的文章,我想使用SQL参数来避免这种情况,但我不知道怎么做。
这是对代码的简单返工。未经测试,但本质上它包括在一次性对象周围添加 using 语句以及使用 SqlCommand 及其参数集合
string connection = ConfigurationManager.ConnectionStrings ["lawyersDBConnectionString"].ConnectionString.ToString();
string sql = "select * from users where userName = @uname and password = @pwd";
DataSet ds = new DataSet();
using(SqlConnection con = new SqlConnection(connection))
using(SqlCommand cmd = new SqlCommand(sql, con))
{
con.Open();
cmd.Parameters.AddWithValue("@uname", username);
cmd.Parameters.AddWithValue("@pwd", password);
using(SqlDataAdapter da = new SqlDataAdapter(cmd))
{
User user = new User();
DataRow dr;
da.Fill(ds);
dr = ds.Tables[0].Rows[0];
user.Id = Convert.ToInt16(dr["userID"]);
user.FirstName = (string)dr["firstName"];
user.LastName = (string)dr["lastName"];
user.Email = (string)dr["email"];
user.Username = (string)dr["userName"];
user.Password = (string)dr["password"];
user.type = (string)dr["type"];
return user;
}
}
请注意,命令文本并不直接包含用户和密码的字符串,而是一个简单的参数占位符(@uname and @pwd)
。将参数添加到 SqlCommand 集合时,这些占位符称为参数名称。
查看检索到的数据的使用情况,我强烈建议您查看简单的ORM工具,例如Dapper,它们可以直接翻译User对象中的所有代码。
有趣的是,String.Format 的工作方式与 SQL 参数没有太大区别。唯一真正的区别是,您可以指定每个参数的数据类型,这允许 SQLCommand 正确清理(阅读:防止 sql 注入)用户的输入。
下面是如何更改代码以使用 SQL 参数的示例。
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("select * from users where userName = @pUsername and password = @pPassword", connection))
{
command.Parameters.Add(new SqlParameter("pUsername", username));
command.Parameters.Add(new SqlParameter("pPassword", password));
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter(command);
// The rest of your code here...
}
}
不过,我想指出几点:
- 用户名通常不区分大小写,因此查询可能应该使用 LIKE 或 UCASE() 比较来查找用户名。
- 从查询中可以明显看出,您的密码没有经过哈希处理或加盐处理。这是非常糟糕的。阅读散列密码。https://crackstation.net/hashing-security.htm
- 基本上,您在此处创建的称为对象关系管理器。除非你特别有兴趣学习如何开发一个,否则我强烈建议你使用一个经过尝试和测试的。就个人而言,我使用nHibernate。Hibernate是作为Java的ORM编写的,nHibernate在.Net应用程序中非常流行。实体框架是Microsoft的ORM。我认为它还没有与nHibernate相提并论,但它在不断改进。
这是我为满足需求编写的可重用方法:
public static DataSet GetDataSetWithParameters(string query, List<SqlParameter> parameters)
{
DataSet ds = new DataSet();
SqlConnection Con = new SqlConnection(ConnectionString);
Con.Open();
try
{
using (SqlCommand cmd = new SqlCommand(query, Con))
{
if (parameters != null)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
using (SqlDataAdapter Adapter = new SqlDataAdapter(cmd))
{
Adapter.Fill(ds);
}
return ds;
}
}
catch
{
throw;
}
finally
{
CloseConnection(ref Con);
}
}