SQLServer数据访问
两大类数据访问方式:
1.轻量级:SqlConnection,SqlCommand,SqlDataReader
2.重量级(内存占用量比较大):SqlConnection,SqlDataAdapter,DataTable
步骤:
1、建立链接对象——建一个通向数据库的通道。
2、打开通道
3、操作数据库
4、关闭通道
五大对象:
链接对象,命令对象,读取器对象,适配器对象,数据集(数据表)
对象介绍:
命名空间:
操作SQLServer数据库:
using System.Data;
using System.Data.SqlClient; //针对SqlServer进行优化了的数据访问类的空间
System.Data.OleDB;System.Data.ODBC; //命名空间通用数据访问类的空间。
ODBC——Open DataBase Connection开放式数据互联
一、连接对象(SqlServer):SqlConnection
(一)构造:
SqlConnection()
SqlConnection(连接字符串)
连接字符串的写法。
第一种:手写 "server=.;database=mydb;uid=sa;pwd=sa";
第二种:使用服务器资源管理器,通过添加链接用可视化界面生成链接对象,通过查看属性来获得连接字符串。(菜单栏中“视图”→“服务器资源管理器”→右键→“添加连接”→选择“Sql Server”→VS窗口右边的“属性”→“链接字符串”)
(二)属性:
ConnectionString:字符串,设置或获取链接对象的连接字符串。
State:ConnectionState枚举类型,返回当前连接状态。
(三)方法:
Open():void,打开连接
Close():void,关闭连接
CreateCommand():SqlCommand,创建命令对象,生成一个通过本链接对象来访问数据库的SqlCommand实例。(好处是,不用对命令对象单独设置Connection属性)
(四)代码:
SqlConnection conn = new SqlConnection("server=.;database=mydb;uid=sa;pwd=sa");//创建连接通道
try
{
conn.Open();
....
}
finally
{
conn.Close();
}
如何在App.Config配置文件中配置数据库连接字符串
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="sql" connectionString="server=.\sqlexpress;database=mydb;uid=sa;pwd=sa"/>
</connectionStrings>
读取App.Config中的链接字符串
public class DBConnection
{
public static SqlConnection Connection
{
get
{
//从配置文件中读取链接字符串
string connectionString = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
SqlConnection conn = new SqlConnection(connectionString);
return conn;
}
}
}
string connectionString = ConfigurationManager.ConnectionStrings["sql"].ConnectionString;
注意: 1.需要添加System.Configuration引用。
2.需using System.Configuration命名空间。
二、命令对象(SqlServer):SqlCommand
(一)构造:
SqlCommand()
SqlCommand(string sql)
SqlCommand(string sql,SqlConnection conn)
conn.CreateCommand() //通过连接通道创建命令对象。
(二)属性:
CommandText //string,要执行的SQL命令——SQL语句,存储过程名。
CommandType //Commandtype,枚举类型
CommandType.Text //SQL语句(默认)。
CommandType.StoredProcedure //存储过程。
如何调用存储过程?
1.把CommandText赋为存储过程的名。
2.把CommandType赋为CommandType.StoredProcedure。
3.使用cmd.Parameters.AddWithValue()为存储过程参数赋值。
Connection //SqlConnection对象。执行命令时,所使用连接对象。
Parameters //SqlParameterCollection,当CommandText中使用SqlServer局问变量时,需要通过该属性来对变量赋值。
(三)方法:
ExecuteNonQuery(); //int,执行SQL命令,返回影响的行数。一般用来执行增、删、改
ExecuteReader(); //SqlDataReader,执行SQL命令,返回数据读取器。一般用来执行查询
ExecuteScalar(); //object,执行SQL命令,返回首行首列,一般用来执行统计(count(),sum(),avg(),max(),min())查询的。
例:int count=(int)ExecuteScalar();
(四)重要代码:
SqlConnection conn = new SqlConnection("server=.;database=mydb;uid=sa;pwd=sa"); //创建连接
//SqlCommand cmd = new SqlCommand();
//cmd.Connection = conn;
SqlCommand cmd = conn.CreateCommand(); //创建命令对象
//设置命令的类型
cmd.CommandType = CommandType.Text; //如果要调用存储过程:cmd.CommandType = CommandType.StoredProcedure;
//指定SQL命令
cmd.CommandText = "insert into nation values(@code,@name) ";
//添加命令参数
cmd.Parameters.AddWithValue("@code","n005");
cmd.Parameters.AddWithValue("@name","壮族"); //为SQL命令中的变量赋值。下面为另一种变量赋值方式
//SqlParameter paramCode = new SqlParameter("@code","n005");
//cmd.Parameters.Add(paramCode);
//SqlParameter paramName = new SqlParameter("@name","壮族");
//cmd.Parameters.Add(paramName);
try
{
conn.Open();
cmd.ExecuteNonQuery();
}
finally
{
conn.Close();
}
SQL注入攻击,原理分析及对策(单引号替换,使用SQL局部变量)。
所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
规避办法:
1.把单引号替换成双引号;
2.修改查询语句,使用SQLSERVER的局部变量来传递参数。(使用cmd.Parameters.AddWithValue()来解决)
三、读取器对象(SqlServer):SqlDataReader
只读,只向前的数据读取对象。
它不是结果集,它内存中只占一条数据的空间。每次读取下一条时,会把内存中当前条的内容覆盖。
(一)构造:
不能直接new出来,原因是,它的构造函数是非public的。
只有唯一的生成方式:cmd.ExecuteReader([CommandBehavior.CloseConnection]);
例:SqlDataReader dr = cmd.ExecuteReader();
(二)属性:
.HasRows //返回bool型数据,判断读取器中是否查出数据。
(三)方法:
.Read(); //读取下一条数据到内存中来。返回bool型数据。
.Close(); //关闭读取器。一般不会关闭链接,但如果读取器生成的时候Command对象的ExecuteReader()方法中带有CommandBehavior枚举型参数的话,可能把连接也给关掉。
dr[“列名”]; //读取内存中当前SqlDataReader对象中的某列数据,读出来的数据是Object类型。
dr[索引号]; //读取内存中当前SqlDataReader对象中的某列数据,读出来的数据是Object类型。
dr.GetString(索引号),dr.Getint(索引号)……
(四)重要代码:
string connectionString = @"server=.\sqlexpress;database=mydb;uid=sa;pwd=sa";
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "select * from info";
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Console.WriteLine(dr["Code"].ToString()+dr["Name"].ToString());
}
conn.Close();
注意事情:
1.登录判断。
查询返回SqlDataReader,使用HasRows属性来判断是否查出记录来,登录是否成功。
SqlDataReader dr = cmd.ExecuteReader();
if(dr.HasRows)
{
}
2.查询多行数据出来,演示多行显示
SqlDataReader dr = cmd.ExecuteReader();
while(dr.Read())
{
Console.WriteLine(dr["列名"].ToString()+(bool)dr[1]); //dr[常用的两种方式];dr[0],dr["列名"]返回的都是object
}
四、DataTable/DataSet
DataSet相当于内存中的数据库,其中包括多个DataTable。
DataTable相当于内存中的数据表。其中包括两个最重要的属性:Rows(DataRowCollection),Columns(DataColumnCollection)。分表代表:表的行集合和列集合。
(一)手动造DataTable
//造表
DataTable table = new DataTable();
//造列
DataColumn col1 = new DataColumn("列名","类型","长度");
DataColumn col2 = new DataColumn("列名","类型","长度");
DataColumn col3 = new DataColumn("列名","类型","长度");
table.Columns.Add(col1);
table.Columns.Add(col2);
table.Columns.Add(col3);
//造行
DataRow row1 = table.NewRow(); //用表对象来生成行结象
row1[0] = "";
row1["列名"] = "";
row1[2] = "";
table.Rows.Add(row1);
DataRow row2 = table.NewRow(); //用表对象来生成行结象
row2[0] = "";
row2["列名"] = "";
row2[2] = "";
table.Rows.Add(row2);
DataRow row3 = table.NewRow(); //用表对象来生成行结象
row3[0] = "";
row3["列名"] = "";
row3[2] = "";
table.Rows.Add(row3);
假设表中已经查出数据来了,我要取某个数据,怎么取法?
例如:假设查出一个数据表table的数据来。
1.我要操作第3行第5列的数据。(假设我从1开始数的列号和行号)。不能先读取列,因为一行才是一条完整的记录。
string s = table.Rows[2][4].ToString(); //取值
table.Rows[2][4] = "hello world";//赋值
2.我要操作所有的数据
for(int i=0;i<table.Rows.Count;i++)
{
for(int j=0;j<table.Columns.Count;j++)
{
Console.Write(table.Rows[i][j].ToString());
}
}
3.控件绑定:
xxx.DataSource = table;
(二)使用可视化界面造
五、数据适配器对象:SqlDataAdapter
适本器对象中包含四大SqlCommand属性:
SelectCommand
InsertCommand
DeleteCommand
UpdateCommand
两大方法:
Fill(DataTable/DataSet)
Update(DataTable/DataSet)
数据访问有两种不同的方式,一种是用Connection, Command , DataReader来进行数据对数据的操作,另一种是用DataAdapter(适配器)来进行数据操作,而数据则一般放在内存中的数据集合DataSet,这种方式可以在内存中对数据操作,然后在合适的时间再将修改传到数据库。
(一)手写代码操作(简单了解)
(二)可视化界面操作。
1、建立数据集。
1)、在解决方案上点右键→“添加”→“新建项”→在左侧“数据”列表中找到“数据集”
2)、在服务器资源管理器中添加连接
3)、在数据库中找到需要的表,然后选中并拖动到右侧的数据集中
2、在数据集中添加新查询
1)、选中一个TableAdapter,右键→“配置”→打开“高级选项”→去掉后两项
2)、右键TableAdapter→“添加查询”→“使用SQL语句”→选择SQL语句类型→编写SQL语句→修改方法名称→完成
3、使用
1)、 造适配器对象:
InfoTableAdapter info = new InfoTableAdapter();
2)、造内存表对象
Mydb.InfoDataTable table = new Mydb.InfoDataTable();
3)、 查询返回
table = info.GetData();
4)、修改
InfoTableAdapter adp = new InfoTableAdapter();
info.UpdateBycode(name, sex, nation, birthday, code);
数据访问相关类的封装:连接类,实体类,数据访问类
装箱与拆箱:Boxing,Unboxing
值类型数据与引用类型数据之间的转化。
装箱:把数据从值类型变成引用类型;把数据由栈空间转型到堆空间。
拆箱:把数据从引用类型变成值类型;把数据由堆空间转型到栈空间。
int n = 19;
object obj = n; //装箱
n = 20;
int m = (int)obj;//拆箱
有什么坏处?
装箱:占空间,占时间,运行慢。
拆箱:占用时间,可能出现类型异常