Ado.net总结
Connetion对象
作用:
1. 连接数据库
2. 创建Command对象
3. 创建Transaction对象
重要属性
1. ConnectionString
2. State 其值包括 Closed Open
连接池
1. Ado.Net的连接池默认是打开的。如果数据库连接在60秒内未被再次使用,系统会自动关闭连接。当调用close方法时实际上是把连接放回到池中。
重要方法
1. Open()
2. Close()
3. CreateCommand()
4. BeginTransaction()
Command对象和DataReader对象
Command作用
1. 执行sql 语句
2. 执行存储过程
3. 执行视图
DataReader作用
1.装载结果集
创建Command对象的方法有三种
1. Command cmd = Con.CreateCommand();
2. Command cmd= new Command(sql,con);
3. Command cmd= new Command(sql,con,trans);
4. Command cmd= new Command();
重要知识点
1. cmd.ExecuteReader();
这个方法返回的结果集存储在DataReader中,它的游标是仅向前且只读的(流水游标)DataReader的read方法可以读取结果集数据
OleDbDataReader rdr = cmd.ExecuteReader();
while(rdr.read())
Conlole.write(rdr[“CustomerID”]);
2. OleDbDataReader读取数据的三种方式
1:rdr[“ColumnName”]
2:rdr[ColumnIndex];
3. OleDbDataReader的NextResult方法获取多个结果集
string strsql=”select * from t1;select * from t2”;
SqlCommand cmd = new SqlCommand(strsql,conn)
OleDbDataReader rdr = cmd.ExecuteReader();
do{
while(rdr.read()) {
Console.writeline(rdr[0]+rdr[1]);
}
Console.writeline();
}while(rdr.NextResult());
4. 关闭DataReader对象
尽可能迅速关闭DataReader对象是非常重要的,一个带有开放DataReader的Connection对象仍然被认为是锁定的。如果你在关闭一个DataReader之前试图打开第二个DataReader对象就会报错。例如:
SqlCommand cmd = new SqlCommand("select * form jobs",con);
SqlDataReader dr= cmd.ExecuteReader();
SqlCommand cmd1 = new SqlCommand("select * form jobs",con);
SqlDataReader dr1= cmd.ExecuteReader();
DataReader对象是出于性能方面的原因考虑的。如果需要在结果集的行之间前后移动就应该使用DataSet对象。
5. cmd.ExecuteNonQuery();
可以返回影响记录的行数,也可以不要返回值,主要用于执行增删改,不包括查询。
6.
Convert.ToInt32与int32.parse的区别 前一个是将差不多所有的类型转换为int32,而后以这只是将一个字符串形式的数转换为int32。 convert.toint32(1234.32)是正确的。 而int32.parse(1234.21)就不对了。 |
OleDbCommand cmd = cn.CreateCommand();
cmd.CommandText=”select count(*) from Customers”;
int counts=Convert.ToInt32(cmd.ExecuteScalar());
7. 执行参数查询
参数标记是以@开头的变量
string sql=”select * from jobs where job_id=@id”;
OleDbCommand cmd=new OleDbCommand(sql,cn);
cmd.Parameters.add(“@id”,OleDbType.int);
cmd.Parameters[0].value=1;
OleDbDataReader rdr=cmd.ExecuteReader();
rdr.read();
8. 调用存储过程无输出参数
SqlCommand cmd= con.CreateCommand();
cmd.CommandText="procName";
cmd.CommandType =CommandType.StoredProcedure ;
cmd.Parameters.Add("@procParam",DbType.Int32);
cmd.Parameters[0].Value="5";
SqlDataReader dr1= cmd.ExecuteReader();
9. 调用存储过程有输出参数
Create porc test
@customerID int,
@outParam varchar(20) output
as
……
SqlCommand cmd= con.CreateCommand();
cmd.Connection =cn;
cmd.CommandText="{CALL test(?,?)}";
cmd.Parameters.Add("@customerID ",DbType.Int32);
cmd.Parameters.Add("@procParam",DbType.string);
cmd.Parameters[“@ customerID”].Value="5";
cmd.Parameters[“@procParam”].Direction=ParameterDirection.Output;
cmd.ExecuteNonExecute();
Console.writeline(Convert.ToInt32(cmd.Parameters[“@procParam”].Value));
10. 在Command中执行事务Transaction
SqlTransaction tran= con.BeginTransaction();
string sql="select * from t1";
//SqlCommand cmd = new SqlCommand(sql,con,tran);
SqlCommand cmd = con.CreateCommand();
cmd.Transaction=tran;
cmd.ExecuteNonQuery();
tran.Commit();
//tran.Rollback();
Command重要属性
CommandText
l CommandType .Text
l CommandType .StoredProcdure
l CommandType .TableDirect
CommandType
Connection
Parameters
Transaction
Command重要方法
CreateParameter()
ExecuteNonQuery()
ExecuteReader()
ExecuteScalar()
DataReader重要属性
FieldsCount
isClosed
DataReader重要方法
Read()
Close()
Parameter重要属性
DataType 参数对象的数据类型
DbType 参数的数据库数据类型sql
Direction
l Input
l Output
l ReturnValue
OleDbType OleDb数据类型
SourceColumn
SourceVersion
Value
DataAdapter对象
作用:DataAdapter类是ADO.NET对象模型中联机和脱机两部分的桥梁。可以使用DataAdapter将数据库的数据取出来放到DataSet中去,也可以将DataSet中的数据修改提交给数据库。
这里只介绍DataAdapter将数据库的数据取出来放到DataSet中去,后边在介绍将DataSet中的数据修改提交给数据库。
创建DataAdapter
注意使用相同连接的问题
方法1
不使用Connection,这种情况SqlDataAdapter每次建立一个Connection,使用后又关闭了Connection。
string constr="server=.;database=pubs;uid=sa;pwd=";
string sql="select * from jobs";
SqlDataAdapter adap= new SqlDataAdapter(sql,constr);
DataSet ds= new DataSet();
adap.Fill(ds);
dataGrid1.DataSource=ds.Tables[0].DefaultView;
方法2
使用Connection,每次使用相同的Connection
string constr="server=.;database=pubs;uid=sa;pwd=";
SqlConnection con= new SqlConnection(constr);
con.Open();
string sql="select * from jobs";
string sql1="select * from tt";
SqlDataAdapter adap= new SqlDataAdapter(sql,con);
SqlDataAdapter adap1= new SqlDataAdapter(sql1,con);
DataSet ds= new DataSet();
adap.Fill(ds);
dataGrid1.DataSource=ds.Tables[0].DefaultView;
1. 设计DataAdapter的目的是处理脱机数据
2. 在DataAdapter和DataSet之间没有直接连接,当数据Fill完成之后两者之间就没有连接了
adap.Fill(ds);
3. DataAdapter中包含用于向数据库回传存储在DataSet中的改动的更新逻辑,而且更新逻辑有我们自己控制。它们是
SelectCommand
InsertCommand
UpdateCommand
DeleteCommand
4. Fill方法
Adap.Fill(ds); //DataSet中的表名称默认为table table1 table2…
Adap.Fill(ds,”DataSetTableName”); //DataSet中的表名称为DataSetTableName
5. 多次调用Fill方法将数据装载到DataGrid中会出现数据重复显示,解决方法
1.每次重新new DataSet()
DataAdapter重要属性
SelectCommand
InsertCommand
UpdateCommand
DeleteCommand
DataAdapter重要方法
Fill()
Update()
DataSet,DataTable,DataRow,DataColumn对象
1. DataSet的特性
1. 处理脱机数据
2. 浏览、排序、搜索、过滤
3. 处理数据关系
4. 缓存更改
2. 创建DataSet对象
DataSet ds=new DataSet();
3. 填充数据集DataSet
SqlDataAdapter adap=new SqlDataAdapter(sql,con);
DataSet ds=new DataSet();
adap.Fill(ds,”tableName”);
4. DataTable对象和DataColumn对象
adap=new SqlDataAdapter("select * from tt",con);
adap.Fill(ds,"dstt");
DataTable dt=ds.Tables[0];
for(int i=0;i<dt.Columns.Count ;i++){
Console.WriteLine(dt.Columns[i].ColumnName);
}
foreach(DataColumn col in dt.Columns){
Console.WriteLine(col.ColumnName);
}
5. 查看DataAdapter返回的数据
DataRow对象:返回DataTable中的一行数据
adap=new SqlDataAdapter("select * from tt",con);
adap.Fill(ds,"dstt");
DataTable dt=ds.Tables[0];
DataRow dr=dt.Rows[0];
Console.WriteLine(dr[0]);
Console.WriteLine(dr[1]);
static void DisplayRow(DataRow row)
{
DataTable tbl=row.Table;
foreach(DataColumn col in tbl.Columns)
{
Console.WriteLine(col.ColumnName+row[col]);
}
}
foreach(DataRow row in tbl.Rows)
{
DisplayRow(row);
}
注意:DataRow没有Column属性,Column属性在DataTable中,通过
DataTable tbl=row.Table;得到DataTable
DataRow.RowState属性公开,如下表:
成员名称 |
说明 |
Added |
该行已添加到 DataRowCollection 中,AcceptChanges 尚未调用。 |
Deleted |
该行已通过 DataRow 的 Delete 方法被删除。 |
Detached |
该行已被创建,但不属于任何 DataRowCollection。DataRow 在以下情况下立即处于此状态:创建之后添加到集合中之前;或从集合中移除之后。 |
Modified |
该行已被修改,AcceptChanges 尚未调用。 |
Unchanged |
该行自上次调用 AcceptChanges 以来尚未更改。 |
一个DataRow对象刚被创建之后其状态是Detached,是孤立的一个存在,所以建立了DataRow之后在DataRow中的单元填充了数据后还要通过DataTable.Rows.Add(DataRow)方法将此DataRow添加到DataTable,DataRow添加到DataTable后, 这个DataRow的状态就转变为Added。当修改了这个DataRow后,这个DataRow状态转为Modified,当用DataRow.Delete()方法删除DataRow后,DataRow状态将转为Deleted,不过此行还存在在DataTable中的,只是状态改变了,这时用DataTable.Rows.Count查看行数,跟删除前是一样的。只有在调用了DataTable.Remove(DataRow)方法后,此DataRow才被从DataTable移除,状态也回复到Detached孤立状态。
6. 校验DataSet中的数据
DataColumn列级约束
ReadOnly
AllowDBNull
MaxLength
Unique
DataTable表级约束
UniqueConstraints
Primarykey
ForeignkeyConstraints
7. DataTable对象编程
7.1创建DataTable对象
DataTable tbl= new DataTable(“TableName”);
7.2将DataTable添加到DataSet对象的Table集合中
ds.Tables.Add(tbl);
7.3为DataTable添加列
DataColumn col = tbl.Columns.Add(“CustomerID”);
7.4指定DataColumn的数据类型
DataColumn col = tbl.Columns.Add(“CustomerID”,typeof(int));
7.5添加主键
tbl.PrimaryKey=new DataColumn[]{tbl.Columns["OrderID"],tbl.Columns["ProductID"]};
7.6添加其他约束
col.AllowDBNull=false;
col.MaxLength=5;
col.Unique=true;
tbl.Constraints.Add(new UniqueConstraint(cols));
7.7处理自动增量
SqlConnection con = new SqlConnection("server=.;uid=sa;pwd=;database=pubs");
con.Open();
DataSet ds= new DataSet();
DataTable tbl = new DataTable("table1");
DataColumn colid=tbl.Columns.Add("id",typeof(int));
DataColumn colage=tbl.Columns.Add("age",typeof(int));
colid.AutoIncrement=true;
colid.AutoIncrementSeed=1;
colid.AutoIncrementStep=1;
ds.Tables.Add(tbl);
dataGrid1.DataSource=ds.Tables[0].DefaultView;
8. 修改DataTable内容
8.1添加新的DataRow
DataRow row = ds.Tables[0].NewRow;
Row[0]=”new Value”
Ds.tables[0].Rows.Add(row);
8.2修改当前行
方法一:row[“CompanyName”]=”NewCompanyName”;
8.3处理DataRow空值
If(row.IsNull(“ColumnName”)){
row[“ColumnName”]=DBNull.Value;
}
注意:当值为null时使用System.DBNull类的Value属性为DataRow赋值
8.4删除DataRow
row.Delete();
注意:这实际上是将该行挂起
8.5清除DataRow
DataRow dr = ds.Tables[0].Rows[1];
ds.Tables[0].Rows.Remove(dr);
Tbl.clear();//清除所有的记录
ds.Clear();//清除ds所有table中的数据
DataSet对象的属性
Tables
DataSet对象的方法
AcceptChanges() //接受DataSet里所有的挂起更改
Clear()
HasChanges()
DataTable对象的属性
Columns
Rows
DataSet
DefaultView
PrimaryKey
TableName
DataTable对象的方法
AcceptChanges()
Clear()
NewRow
DataColumn对象的属性
AllowDBNull boolean
AutoIncrement Boolean
AutoIncrementSeed
AutoIncrementStep
ColumnName
DataType
DefaultValue
MaxLength
ReadOnly
Table
Unique
DataRow对象的属性
Table
DataRow对象的方法
AcceptChanges()
Delete()
isNull()
DataRelation对象
作用:创建表之间的关系
说明:DataRelation与ForeignKeyConstraints都是设置表关系的。区别如下:
1.DataRelation对象属于DataSet对象
2.ForeignKeyConstraints对象属于DataTable对象
3.在创建DataRelation时会自动创建ForeignKeyConstraints,而且如果ForeignKeyConstraints对象如果在创建DataRelation之前已经创建好的话,DataRelation对象就直接引用ForeignKeyConstraints对象。
1. 创建DataRelation对象
DataRelation rel= new DataRelation("约束名称",主表.主键,从表.外键);
DataRelation rel= new DataRelation("CustomerOrders",
ds.Tables["Customers"].Columns["CustomersID"],
ds.Tables["Orders"].Columns["CustomersID"]);
2. DataRow对象的GetChildRows方法
该方法用于查找主表中主键对应的从表的外键行
foreach(DataRow rowCustomer in ds.tables[“Customers”].Rows)
{
foreach(DataRow rowOrder in rowCustomer.GetChildRows(“RelationName”))
Console.WriteLine(rowOrder[“OrderDate”]);
}
3. DataRow对象的GetParentRow方法
该方法用于查找从表的外键对应主表中的主键行
foreach(DataRow rowOrder in ds.tables[“Orders”].Rows)
{
DataRow Customer = rowOrder.GetParentRow(“RelationName”)
Console.WriteLine(Customer [“CompanyName”]);
}
DataTable对象的排序,搜索,筛选。
1. tbl.Rows.Find方法
该方法接受一个包含要查找行的主键值的对象,因为主键值是唯一的,所以Find方法只能返回一个DataRow对象。
Tbl.PrimaryKey = new DataColumn[ ] { tbl.columns[“CustomerID”] }
DataRow row = tbl.Rows.Find(“ALFKI”)
If (row==null){
Console.writeline(“row not found”);
}else{
Console.writeline(row[“CompanyName”]);
}
当主键是由表级主键构成的,应该这样处理。
Tbl.PrimaryKey = new DataColumn[ ] { tbl.columns[“CustomerID”], tbl.columns[“ProductID”]};
Object obj = new Object[]{10643,28}
DataRow row = tbl.Rows.Find(obj)
If (row==null){
Console.writeline(“row not found”);
}else{
Console.writeline(row[“CompanyName”]);
}
2. tbl.select 方法
该方法类似于sql语句中的where
DataTable tbl= new DataTable();
DataRow []aRows = tbl.Select("country='usa' and city='Seattle'")
foreach(DataRow row in aRows){
Consolw.wirteline(row["country"]);
}
3. 通配符% *
DataTable tbl= new DataTable();
DataRow []aRows = tbl.Select("country like ‘New %’ ")
foreach(DataRow row in aRows){
Consolw.wirteline(row["country"]);
}
4. 排序
DataTable tbl= new DataTable();
DataRow []aRows = tbl.Select("country like ‘New %’ ", “City desc”)
foreach(DataRow row in aRows){
Consolw.wirteline(row["country"]);
}
DataView对象
DataTable 对象的Select 方法是强大的,灵活的,但是他并不总是最佳的解决方案。它主要有两方面的局限性。其一,由于他接受动态搜索条件,所以它并不是很高效。其二,Windows 和 web 窗体都不支持绑定到Select方法的返回值(即一个DataRow数组),因此Ado.net引入的DataView对象。
DataView对象不维护自己的数据副本。当您通过DataView访问数据时,DataView将返回存储在相应的DataTable中的数据。
DataView可以用来筛选,排序,搜索DataTable中的内容,但是他们不是sql语句,不能使用DataView在两个DataTable对象之间使用jion查询。
不能使用DataView查询DataTable中的部分列,必须全部查询。
一个DataView只能访问一个DataTable。
1. DataView解决多DataTable查询问题
将表的列通过关系添加到子表中
Ds.Relations.Add(“CustomerOrders”,
ds.tables[“Customers”].Columns[“CustomerID”], ds.tables[“Orders”].Columns[“OrdersD”])
ds.Tables[“Orders”].Columns.add(
“CompanyName”, typeOf(string),
”parent(CustomerOrders).CompanyName”)
2. 使用DataView对象
DataTable tbl = new DataTable(“TableName”); // tableName是必须的
DataView vue;
Vue = new DataView();
Vue.Table=tbl;
// Vue = new DataView(tbl);
3. DataView对象的筛选,排序
DataViewRowState d;
DataView vue;
DataTable tbl;
d=DataViewRowState.ModifiedOriginal | DataViewRowState.Deleted ;
tbl = new DataTable(“TableName”);
// tableName是必须的,否则tbl对象没有表名称,无法绑定到datagrid控件,但是从DataSet中取出来的DataTable可以没有表名称,因为他有默认的表名称table0 table1 等等。
Vue = new DataView();
Vue.RowFilter=”Country=’USA’”;
Vue.Sort=”City Desc”;
Vue.RowStateFilder=d;
// Vue = new DataView(tbl ,”Country=’USA’ ”,”City desc”,d);
4. 使用DataRowView 对象
DataTable tbl = new DataTable(“customers”)
DataView vue = new DataView(tbl);
DataRowView vRow=vue[0];
Console.wirteline(row[“CompanyName”]);
DataRow dRow = vRow.row;
5. 通过DataView查看所有可用行
for(int i=0;i<vue.Count;i++){
DataRowView row=vue[i];
Console.Writeline(row[“CompanyName”]);
}
IEnumerator obj = vue.GetEnumerator();
While (obj.Movenext()){
Row= (DataRowView)obj.Current;
Console.Writeline(row[“CompanyName”]);
}
6. Find方法
一旦设置了DataView对象的Sort属性,就可以调用它的Find方法,Find方法根据Sort属性中所指定的列来查找。但是他并不返回DataRow或DataRowView对象,而是返回一个整型值,该值对应被查找行的索引。如果不能查找到,返回-1
DataView vue = new DataView(tbl);
Vue.sort=”CompanyName”;
Int intindex=vue.Find(“Fran Wilson”);
If (intindex==-1){
Console.writeline(“Row not found”);
}else{
Console.writeline(vue[intindex][“CompanyName”]);
}
7. FindRows方法
该方法返回DataRowView对象数组
DataRowView [] aRows = vue.FindRows(“Spain”);
If(aRows.Length==0){
Console.writeLine(“No row found”);
}else{
Foreach(DataRowView row in aRows){
Console.writeLine(row[“city”]);
}
}
//通过DataTable 添加新行
private void button1_Click(object sender, System.EventArgs e)
{
conn=new SqlConnection("server=.;uid=sa;pwd=;database=ggjxc");
adap= new SqlDataAdapter("select * from 用户表",conn);
ds=new DataSet();
adap.Fill(ds,"用户表");
DataRow drow=ds.Tables[0].NewRow();
drow["用户名"]="username";
drow["密码"]="username";
drow["姓名"]="username";
tbl.Rows.Add(drow);
dataGrid1.DataSource=ds.Tables["用户表"].DefaultView;
}
//通过DataView修改一行
private void button1_Click(object sender, System.EventArgs e)
{
conn=new SqlConnection("server=.;uid=sa;pwd=;database=ggjxc");
adap= new SqlDataAdapter("select * from 用户表",conn);
ds=new DataSet();
adap.Fill(ds,"用户表");
DataView vue=new DataView(ds.Tables["用户表"]);
vue.Sort="用户名";
int intindex=vue.Find("sjx");
DataRowView row=vue[intindex];
row.BeginEdit();
row["用户名"]="new username";
row.EndEdit();
dataGrid1.DataSource=ds.Tables["用户表"].DefaultView;
}
//删除一行
Row.delete();
8. RowFilter属性
该属性能够过滤DataView中的行
private void button1_Click(object sender, System.EventArgs e)
{
conn=new SqlConnection("server=.;uid=sa;pwd=;database=ggjxc");
adap= new SqlDataAdapter("select * from 用户表",conn);
ds=new DataSet();
adap.Fill(ds,"用户表");
DataView vue=new DataView(ds.Tables["用户表"]);
vue.RowFilter="用户编号>1";
dataGrid1.DataSource=vue;
}
DataAdapter对象的更新逻辑
private SqlConnection conn;
private SqlDataAdapter adap;
private DataSet ds;
private SqlParameter sqlpara;
private void button1_Click(object sender, System.EventArgs e)
{
conn=new SqlConnection("server=.;uid=sa;pwd=;database=ggjxc");
adap= new SqlDataAdapter("select * from 用户表",conn);
ds=new DataSet();
adap.Fill(ds,"用户表");
dataGrid1.DataSource=ds.Tables[0].DefaultView;
}
private void button3_Click(object sender, System.EventArgs e)
{
string sql="update 用户表 set 密码=@pass where 用户名=@username";
adap.UpdateCommand=new SqlCommand(sql,conn);
sqlpara=adap.UpdateCommand.Parameters.Add("@username",SqlDbType.VarChar);
sqlpara.SourceColumn="用户名";
sqlpara.SourceVersion =DataRowVersion.Current ;
sqlpara=adap.UpdateCommand.Parameters.Add("@pass",SqlDbType.VarChar);
sqlpara.SourceColumn ="密码";
sqlpara.SourceVersion =DataRowVersion.Current ;
if (ds.HasChanges()){
adap.Update(ds,"用户表");
// Update delete insert select 与要执行的sql语句和DataGrid的行状态有关
//实际上是找到满足行状态的行来执行sql语句如:
//
string sql="delete from users where username=@username";
adap.DeleteCommand = new SqlCommand(sql,conn);
parm = adap.DeleteCommand.Parameters.Add("@username",SqlDbType.VarChar);
parm.SourceColumn="username";
parm.SourceVersion=DataRowVersion.Original;
ds.Tables[0].Rows[dataGrid1.CurrentRowIndex].Delete();//设置行状态
adap.Update(ds,"users");
//如果行状态没有变化,都是DataRowVersion.Original 增删改查都不会成功
}
}