ADO.NET
概念:ADO.NET就是一组类库,这组类库可以让我们通过程序的方式访问数据库,就像System.IO的类用类操作文件一样,System.Data这组类是用来操作数据库的(不光是MSSql Server),它提供了统一的编程接口让操作其他数据库(Access、Oracle等)的方式和操作MSSQL Server一致
组成:
Connection 连接数据库
Command 执行数据库语句
DataReader 只读只进的结果集
DataAdapter
DataSet 断开时连接的数据库操作
ADO.NET访问数据库的方式:
一、
1、连接数据用Connection
2、执行SQL语句Command
3、执行完毕之后将结果一条一条返回。DataReader
二、
使用DataAdapter+DataSet,这种方法本质还是通过Connection、Command、DataReader将数据全部取出来然后放到了DataSet中。//看DataAdapter的构造函数
ADO.NET连接池
由于每次正常连接数据库都会至少执行三个操作(1、登录数据库服务器 2、执行操作 3、注销用户),所以每次通过Connection向数据库服务器申请一个连接都比较耗时。【ADO.NET默认启用连接池】
为了解决上述问题,ADO.NET采用了连接池的概念
Command对象
操作Sql Server数据库使用SqlCommand对象
SqlCommand表示向服务器提交的一个命令(SQL语句等),CommandText属性为要执行的SQL语句,ExecuteNonQuery方法执行一个非查询语句(Update、Insert、Delete等)
常用的三个方法:
1、ExecuteNonQuery() 执行对数据库的增删改,返回收影响的行数
2、ExecuteScalar() 执行查询,返回首航首列
3、ExecuteReader() 执行查询,返回DataReader对象;执行有多行结果集的用ExecuteReader
HasRow属性返回是否有行
ADO.NET异常处理
在执行数据库操作时,如果数据库服务器未打开,或者sql语句写错了会怎么样?(delete无效、违反约定、数据库服务出问题)
这些情况可以用try...catch...finally来捕获异常
使用异常处理可以保证一个功能出错不影响另一个功能,比如添加操作失败,不影响查询的操作
SQL注入漏洞攻击
登录判断:select * from T_Users where UserName=... and Password=...,将参数拼到SQL语句中。
构造恶意的Password: ' or '1'='1
防范注入漏洞攻击的方法:不使用SQL语句拼接,通过参数赋值
SQL语句使用@UserName表示“此处用参数代替”,向SqlCommand的Parameters中添加参数
参数在SQL Server内部不是简单的字符串替换,SQLServer直接用添加的值进行数据比较,因此不会有注入漏洞攻击
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (IsInput())
{
if (IsLogin(txtUserName.Text.Trim(),txtUserPwd.Text.Trim()))
{
MessageBox.Show("登陆成功");
}
else
{
MessageBox.Show("登陆失败");
}
}
else
{
MessageBox.Show("请完整输入用户名和密码");
}
}
bool IsInput()
{
if (txtUserName.Text.Length==0||txtUserPwd.Text.Length==0)
{
return false;
}
return true;
}
bool IsLogin(string name,string pwd)
{
string conStr = "Data Source = .;Initial catalog = MySchool; uid = sa; pwd = root";
//创建连接对象
using (SqlConnection con = new SqlConnection(conStr))
{
//以下三条语句都可以让攻击者进行Sql漏洞注入攻击
//string sql = "select count(*) from [user] where uname = '" + name + "'and pwd = '" + pwd + "'";
//string sql = string.Format("select count(*) from [user] where uname = '{0}' and upwd ='{1}'", name, pwd);
//string sql = $"select count(*) from[user] where uname ='{name}' and upwd = '{pwd}'";
//使用参数化避免漏洞注入攻击
string sql = "select * from [user] where uname = @name and upwd = @pwd";
//创建command对象
using (SqlCommand cmd = new SqlCommand(sql,con))
{
//开启连接
con.Open();
//创建两个参数对象,把参数和变量的值进行绑定,防止sql漏洞注入
SqlParameter param1 = new SqlParameter("@name", name);
SqlParameter param2 = new SqlParameter("@pwd", pwd);
//把两个参数对象,赋值给cmd对象的Parameters集合进行维护
//解析sql语句的时候,会从Parameters集合中,把两个参数的值,进行提取,然后跟sql进行拼接
//这是避免sql漏洞注入的核心
cmd.Parameters.Add(param1);
cmd.Parameters.Add(param2);
//执行查询,返回一个DataReader对象
SqlDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
return true;
}
else
{
return false;
}
}
}
}
}
}