C#中产生SQL语句的几种方式
(1)拼接产生SQL语句:
string sql = "insert into czyb(yhm,mm,qx) values('" + txtName.Text + "','" + txtPassword.Text + "','" + cmbPriority.Text + "')";
OleDbCommand cmd = new OleDbCommand(sql, conn);
这种方法写法比较复杂,且安全性低,容易遭受SQL注入攻击。
(2)用string.Format方法:
string sql = string.Format("insert into czyb(yhm,mm,qx) values('{0}','{1}','{2}')", txtName.Text, txtPassword.Text, cmbPriority.Text);
只是可读性优于第(1)种。
(3)用参数化SQL语句:
string sql="insert into czyb(yhm,mm,qx) values (@yhm,@mm,@qx)";
OleDbCommand cmd = new OleDbCommand();
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("@yhm", txtName.Text);
cmd.Parameters.AddWithValue("@mm", txtPassword.Text);
cmd.Parameters.AddWithValue("@qx", cmbPriority.Text);
cmd.Connection = conn;
conn.Open();
cmd.ExecuteNonQuery();
代码结构清楚,对于不支持存储过程的数据库(如Access),推荐采用本方法。
(4)如果数据库支持存储过程(如SQL Server),可以调用存储过程执行SQL:
SqlConnection conn = new SqlConnection(txtConn);
SqlCommand cmd = new SqlCommand("SearchContact", conn); //存储过程名称为SearchContact
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@name", SqlDbType.VarChar, 50); //传入参数
cmd.Parameters["@name"].Value = txtName.Text.Trim();
由于存储过程是数据库预编译的,执行效率高,推荐采用。
========
C#连接SQL Server数据库代码解析
连接字符串:
<connectionStrings>
<add name="conn" connectionString="user id=sa;Password=;initial catalog=Northwind;Server=YourSQLServer;Connect Timeout=30;" providerName="System.Data.SqlClient" />
</connectionStrings>
--------------------------------------------------------------------------------
参数介绍(注意:参数间用分号分隔):
"user id=sa":连接数据库的验证用户名为sa.他还有一个别名"uid",所以这句我们还可以写成"uid=sa".
"password=":连接数据库的验证密码为空.他的别名为"pwd",所以我们可以写为"pwd=".
这里注意,你的SQL Server必须已经设置了需要用户名和密码来登录,否则不能用这样的方式来登录.如果你的SQL Server设置为Windows登录,那么在这里就不需要使用"user id"和"password"这样的方式来登录,而需要使用"Trusted_Connection=SSPI"来进行登录.
"initial catalog=Northwind":使用的数据源为"Northwind"这个数据库.他的别名为"Database",本句可以写成"Database=Northwind".
"Server=YourSQLServer":使用名为"YourSQLServer"的服务器.他的别名为"Data Source","Address","Addr".如果使用的是本地数据库且定义了实例名,则可以写为"Server=(local)\实例名";如果是远程服务器,则将"(local)"替换为远程服务器的名称或IP地址.
"Connect Timeout=30":连接超时时间为30秒.
注:以上User ID,Password可以大写也可以小写,与大小写无关
========
用c#读取并分析sql2005日志
用过logExplorer的朋友都会被他强悍的功能吸引,我写过一篇详细的操作文档可以参考
http://blog.youkuaiyun.com/jinjazz/archive/2008/05/19/2459692.aspx
我们可以自己用开发工具来实现sql日志的读取,这个应用还是很酷的,具体思路
1、首先要了解一个没有公开的系统函数::fn_dblog,他可以读取sql日志,并返回二进制的行数据
2、然后要了解sql的二进制数据是如何存储的,这个可以参考我的blog文章
http://blog.youkuaiyun.com/jinjazz/archive/2008/08/07/2783872.aspx
3、用自己擅长的开发工具来分析数据,得到我们需要的信息
我用c#写了一个测试样例,分析了int,char,datetime和varchar的日志情况而且没有考虑null和空字符串的保存,希望感兴趣的朋友能和我一起交流打造属于自己的日志分析工具
详细的试验步骤以及代码如下:
1、首先建立sqlserver的测试环境,我用的sql2005,这个过程不能保证在之前的版本中运行
以下sql语句会建立一个dbLogTest数据库,并建立一张log_test表,然后插入3条数据之后把表清空
use master
go
create database dbLogTest
go
use dbLogTest
go
create table log_test(id int ,code char(10),name varchar(20),date datetime,memo varchar(100))
insert into log_test select 100, 'id001','jinjazz',getdate(),'剪刀'
insert into log_test select 65549,'id002','游客',getdate()-1,'这家伙很懒,没有设置昵称'
insert into log_test select -999,'id003','这家伙来自火星',getdate()-1000,'a'
delete from log_test
--use master
--go
--drop database dbLogTest
2、我们最终的目的是要找到被我们删掉的数据
3、分析日志的c#代码:我已经尽量详细的写了注释
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication21
{
class Program
{
/// <summary>
/// 分析sql2005日志,找回被delete的数据,引用请保留以下信息
/// 作者:jinjazz (csdn的剪刀)
/// 作者blog:http://blog.youkuaiyun.com/jinjazz
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection())
{
conn.ConnectionString = "server=localhost;uid=sa;pwd=sqlgis;database=dbLogTest";
conn.Open();
using (System.Data.SqlClient.SqlCommand command = conn.CreateCommand())
{
//察看dbo.log_test对象的sql日志
command.CommandText = @"SELECT allocunitname,operation,[RowLog Contents 0] as r0,[RowLog Contents 1]as r1
from::fn_dblog (null, null)
where allocunitname like 'dbo.log_test%'and
operation in('LOP_INSERT_ROWS','LOP_DELETE_ROWS')";
System.Data.SqlClient.SqlDataReader reader = command.ExecuteReader();
//根据表字段的顺序建立字段数组
Datacolumn[] columns = new Datacolumn[]
{
new Datacolumn("id", System.Data.SqlDbType.Int),
new Datacolumn("code", System.Data.SqlDbType.Char,10),
new Datacolumn("name", System.Data.SqlDbType.VarChar),
new Datacolumn("date", System.Data.SqlDbType.DateTime),
new Datacolumn("memo", System.Data.SqlDbType.VarChar)
};
//循环读取日志
while (reader.Read())
{
byte[] data = (byte[])reader["r0"];
try
{
//把二进制数据结构转换为明文
TranslateData(data, columns);
Console.WriteLine("数据对象{1}的{0}操作:", reader["operation"], reader["allocunitname"]);
foreach (Datacolumn c in columns)
{
Console.WriteLine("{0} = {1}", c.Name, c.Value);
}
Console.WriteLine();
}
catch
{
//to-do...
}
}
reader.Close();
}
conn.Close();
}
Console.WriteLine("************************日志分析完成");
Console.ReadLine();
}
//自定义的column结构
public class Datacolumn
{
public string Name;
public System.Data.SqlDbType DataType;
public short Length = -1;
public object Value = null;
public Datacolumn(string name, System.Data.SqlDbType type)
{
Name = name;
DataType = type;
}
public Datacolumn(string name,System.Data.SqlDbType type,short length)
{
Name = name;
DataType = type;
Length = length;
}
}
/// <summary>
/// sql二进制结构翻译,这个比较关键,测试环境为sql2005,其他版本没有测过。
/// </summary>
/// <param name="data"></param>
/// <param name="columns"></param>
static void TranslateData(byte[] data, Datacolumn[] columns)
{
//我只根据示例写了Char,DateTime,Int三种定长度字段和varchar一种不定长字段,其余的有兴趣可以自己补充
//这里没有暂时没有考虑Null和空字符串两种情况,以后会补充。
//引用请保留以下信息:
//作者:jinjazz
//sql的数据行二进制结构参考我的blog
//http://blog.youkuaiyun.com/jinjazz/archive/2008/08/07/2783872.aspx
//行数据从第5个字节开始
short index = 4;
//先取定长字段
foreach (Datacolumn c in columns)
{
switch (c.DataType)
{
case System.Data.SqlDbType.Char:
//读取定长字符串,需要根据表结构指定长度
c.Value = System.Text.Encoding.Default.GetString(data,index,c.Length);
index += c.Length;
break;
case System.Data.SqlDbType.DateTime:
//读取datetime字段,sql为8字节保存
System.DateTime date = new DateTime(1900, 1, 1);
//前四位1/300秒保存
int second = BitConverter.ToInt32(data, index);
date = date.AddSeconds(second/300);
index += 4;
//后四位1900-1-1的天数
int days = BitConverter.ToInt32(data, index);
date=date.AddDays(days);
index += 4;
c.Value = date;
break;
case System.Data.SqlDbType.Int:
//读取int字段,为4个字节保存
c.Value = BitConverter.ToInt32(data, index);
index += 4;
break;
default:
//忽略不定长字段和其他不支持以及不愿意考虑的字段
break;
}
}
//跳过三个字节
index += 3;
//取变长字段的数量,保存两个字节
short varColumnCount = BitConverter.ToInt16(data, index);
index += 2;
//接下来,每两个字节保存一个变长字段的结束位置,
//所以第一个变长字段的开始位置可以算出来
short startIndex =(short)( index + varColumnCount * 2);
//第一个变长字段的结束位置也可以算出来
short endIndex = BitConverter.ToInt16(data, index);
//循环变长字段列表读取数据
foreach (Datacolumn c in columns)
{
switch (c.DataType)
{
case System.Data.SqlDbType.VarChar:
//根据开始和结束位置,可以算出来每个变长字段的值
c.Value =System.Text.Encoding.Default.GetString(data, startIndex, endIndex - startIndex);
//下一个变长字段的开始位置
startIndex = endIndex;
//获取下一个变长字段的结束位置
index += 2;
endIndex = BitConverter.ToInt16(data, index);
break;
default:
//忽略定长字段和其他不支持以及不愿意考虑的字段
break;
}
}
//获取完毕
}
}
}
4、更改你的sql连接字符串后运行以上代码,会看到如下输出信息:
数据对象dbo.log_test的LOP_INSERT_ROWS操作:
id = 100
code = id001
name = jinjazz
date = 2008-8-7 18:14:03
memo = 剪刀
数据对象dbo.log_test的LOP_INSERT_ROWS操作:
id = 65549
code = id002
name = 游客
date = 2008-8-6 18:14:03
memo = 这家伙很懒,没有设置昵称
数据对象dbo.log_test的LOP_INSERT_ROWS操作:
id = -999
code = id003
name = 这家伙来自火星
date = 2005-11-11 18:14:03
memo = a
数据对象dbo.log_test的LOP_DELETE_ROWS操作:
id = 100
code = id001
name = jinjazz
date = 2008-8-7 18:14:03
memo = 剪刀
数据对象dbo.log_test的LOP_DELETE_ROWS操作:
id = 65549
code = id002
name = 游客
date = 2008-8-6 18:14:03
memo = 这家伙很懒,没有设置昵称
数据对象dbo.log_test的LOP_DELETE_ROWS操作:
id = -999
code = id003
name = 这家伙来自火星
date = 2005-11-11 18:14:03
memo = a
************************日志分析完成
试验成功~~
dbcc log和fn_dblog函数真的是分析日志文件吗?
这个问题需要了解CheckPoint和sql的存储机制,首先参考如下文档
http://msdn.microsoft.com/zh-cn/library/ms188748.aspx
CheckPoint
将当前数据库的全部脏页写入磁盘。“脏页”是已输入缓存区高速缓存且已修改但尚未写入磁盘的数据页。CHECKPOINT 可创建一个检查点,在该点保证全部脏页都已写入磁盘,从而在以后的恢复过程中节省时间。
什么时候执行它?大致有几种情况:
手动调用、sql自动定时执行、数据库脱机之类操作、数据库进程正常终止等情况。
简单日志模型的原理就是每次checkpoint后自动截断日志。
dbcc log到底有什么用?和checkpoint有什么关系
在事物外执行过CheckPoint后,dbcc log语句将无法获取之前的日志。所以我推断此语句是系统为了在非正常关闭数据库的状态下,来保证日志,内存中的脏页和数据文件的一致性的措施,此方法并不是读取日志文件的全部信息。
log explorer的原理
还没有搞清楚,此前的推断是错误的,它不是通过dbcc log 或者fn_dblog方法实现的,不但CheckPoint对它没有影响,而且他会主动调用这个语句。
日志分析工具宣告流产,不过基本上搞清了日志和数据文件的存储结构,希望以后仍然可以用的上这些经验
========
解析c#得到局域网内所有sqlserver数据库实例
官方的做法是这样的:
using System.Data.Sql;
class Program
{
static void Main()
{
// Retrieve the enumerator instance and then the data.
SqlDataSourceEnumerator instance =
SqlDataSourceEnumerator.Instance;
System.Data.DataTable table = instance.GetDataSources();
// Display the contents of the table.
DisplayData(table);
Console.WriteLine("Press any key to continue.");
Console.ReadKey();
}
private static void DisplayData(System.Data.DataTable table)
{
foreach (System.Data.DataRow row in table.Rows)
{
foreach (System.Data.DataColumn col in table.Columns)
{
Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
}
Console.WriteLine("============================");
}
}
}
来源于:http://msdn.microsoft.com/en-us/library/system.data.sql.sqldatasourceenumerator.getdatasources.aspx
请看遇到的问题及解决方法:
实际上问题就是,得到的结果只有服务器名字,但由于是默认实例,所以并没有实例名字。而且,假如安装的是sqlserver,则连接数据库是必须是 服务器\sqlexpress(默认实例名称);假如安装的是完整版的sqlexpress,则只需 服务器 即可连接。这就造成了不少问题。 上边百度给出比较好的解决方法。
本文出自 “独钓寒江雪” 博客,请务必保留此出处http://zhaojie.blog.51cto.com/1768828/932275
========
C#数据库查询和操作大全
一:C#数据库查询之数据库连接代码:SqlConnectionobjSqlConnection=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=test");
objSqlConnection.Open();
二:数据库的添加记录代码:
inti=0;
strings1="",s2="";
i=Convert.ToInt16(textBox1.Text);
s1=textBox2.Text;
s2=textBox3.Text;
SqlConnectionobjSqlConnection=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=test");
objSqlConnection.Open();
MessageBox.Show("数据库连接成功","好");
try
{
SqlCommandsqlcom=newSqlCommand("insertintoinfo(id,name,sex)values("+i+",'"+s1+"','"+s2+"')",objSqlConnection);
sqlcom.ExecuteNonQuery();
MessageBox.Show("添加成功!","啊");
}
catch(Exceptiona)
{
MessageBox.Show(a.ToString());
}
MessageBox.Show("添加成功!","啊");
}
三:数据库的修改代码:
inti=0;
strings1="",s2="";
s1=textBox2.Text;
s2=textBox3.Text;
if(textBox1.Text.Length==0)
i=0;
else
i=Convert.ToInt32(textBox1.Text);
SqlConnectionobjSqlConnection=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=test");
objSqlConnection.Open();
MessageBox.Show("数据库连接成功","好");
try
{
SqlCommandsqlcom=newSqlCommand("updateinfosetname='"+s1+"',sex='"+s2+"'"+"whereid="+i,objSqlConnection);
sqlcom.ExecuteNonQuery();
MessageBox.Show("修改成功!","啊");
objSqlConnection.Close();
}
catch(Exceptiona)
{
MessageBox.Show(a.ToString());
}
四:数据库的删除代码:
inti=0;
strings1="",s2="";
s1=textBox2.Text;
s2=textBox3.Text;
if(textBox1.Text.Length==0)
i=0;
else
i=Convert.ToInt16(textBox1.Text);
SqlConnectionobjSqlConnection=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=test");
objSqlConnection.Open();
MessageBox.Show("数据库连接成功","好");
try
{
SqlCommandsqlcom=newSqlCommand("deletefrominfowhereid="+i,objSqlConnection);
sqlcom.ExecuteNonQuery();
MessageBox.Show("删除成功!","啊");
objSqlConnection.Close();
}
catch(Exceptiona)
{
MessageBox.Show(a.ToString());
}
五:数据库的查询代码:
1.类开始:
DataTabledt1=newDataTable();
SqlDataAdapterda1=newSqlDataAdapter();
2.按钮代码:
inti=0,n=0;
strings1="",s2="";
s1=textBox2.Text;
s2=textBox3.Text;
if(textBox1.Text.Length==0)
i=0;
else
i=Convert.ToInt32(textBox1.Text);
SqlConnectionobjSqlConnection=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=test");
objSqlConnection.Open();
MessageBox.Show("数据库连接成功","好");
stringquery="SELECT*frominfowhereid="+i;
DataSetobjDataSet=newDataSet();
SqlDataAdapterobj=newSqlDataAdapter();
obj.SelectCommand=newSqlCommand(query,objSqlConnection);
obj.Fill(objDataSet,"info");
SqlCommandobjSqlCommand=newSqlCommand(query,objSqlConnection);
SqlDataReaderobjSqlReader=objSqlCommand.ExecuteReader();
while(objSqlReader.Read())
{
n+=1;
MessageBox.Show("编号:"+objSqlReader.Getvalue(0)+"姓名:"+objSqlReader.Getvalue(1)+"性别"+objSqlReader.Getvalue(2));
}
if(n==0)
MessageBox.Show("数据库中没有这样的记录!");
六:C#数据库查询代码:
inti=0;
//intn=0;
strings1="",s2="";
stringsql;
s1=textBox2.Text;
s2=textBox3.Text;
if(textBox1.Text.Length==0)
{
i=0;
}
else
i=Convert.ToInt32(textBox1.Text);
SqlConnectionobjSqlConnection=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=test");
objSqlConnection.Open();
MessageBox.Show("数据库连接成功","好");
stringquery="SELECT*frominfowhereid="+i;
if(i==0)
sql="select*frominfo";
else
sql="select*frominfowhereid="+i;
da1=newSqlDataAdapter(sql,objSqlConnection);
dt1.Clear();
da1.Fill(dt1);
dataGridView1.DataSource=dt1;
C#数据库查询之数据库的封装类代码:
classDBClass
{
publicvoiddbclass(stringsql)
{
try
{
SqlConnectionsqlcon=newSqlConnection("server=127.0.0.1;uid=sa;pwd=;database=test");
sqlcon.Open();
SqlTransactionobjt=sqlcon.BeginTransaction();//事物开始
SqlCommandsqlcom=newSqlCommand(sql,sqlcon);
sqlcom.Transaction=objt;//将Command对象设置为事物处理的对象
sqlcom.ExecuteNonQuery();
objt.Commit();//提交事物
sqlcon.Close();
}
catch(Exceptiona)
{
MessageBox.Show(a.ToString());
}
}
}
--db2数据库连接代码:
stringstrcon="Provider=IBMDADB2;DataSource=hfzd;UserId=db2admin;Password=db2admin";
//stringsql="select*fromADMINISTRATOR.HFZD";
stringsql="deletefromADMINISTRATOR.HFZDwhereID=1";
OleDbConnectionolecon=newOleDbConnection(strcon);
olecon.Open();
MessageBox.Show("数据库已连接上");
dt.Clear();
da=newOleDbDataAdapter(sql,olecon);
da.Fill(dt);
dataGridView1.DataSource=dt;
olecon.Close();
========
C#与SQL常用操作
ADO.NET中对数据库的操作是:断开式连接,只需要写一次连接服务器,库名,用户名,密码的字符串,以后只对con 进行close()和con.Open() 操作即可连接数据库
先从数据库中取出结果集后进行处理数据后再UpData更新到数据库(共三步)
如果只想读取和显示数据 则只需使用数据读取器 SqlDataReader即可, 但要处理数据然后更新数据库(增加,更改),就需要用数据集DataSet和
数据适配器SqlDataAdaper
SqlDataAdapter在下面有用法:
其中:读取数据时用SqlDataReader是固定的 但是处理数据更新时(增加,更改)为两种情况,(一)直接拼SQL语句 适用于简单的表,
(二)用参数的 用到SqlDataAdaper 适用于复杂的表
建议:简单的表可以用(一) 但是在实际项目中复杂的表最好用(二)
因为带参数的 要插入或更改的数据结构已被参数欲留位置了,不用对其进行类型转换,当在后面定义了参数后会自动转换,比较简单
其中删除一条记录不用带参数的直接用(一)拼SQL语句 cmd.ExecuteNonQuery()即可
只有insert 和 update 增加和更改用带参数的 如果全部删除也的用带参数的
补充(必看):定义个全局变量 Private SqlConnectionm_con =null;
然后在方法内部 m_con=new 出来
断开式连接体现在:写一个 连接数据库的方法 返回bool值 以后再就不用写连服务器,库名,用户名,密码的字符串了
以后再连接数据库就直接用m_con.Open();即可打开
public bool db_check()//当然复杂时就用传参数形式
{
boolflag=false;
stringConnectionString ="data source =" + dbServerName.Text +";initialcatalog=" + dbName.Text + ";
userid=" +dbUsername.Text + ";password=" +this.dbPassword.Text +";";
try
{
m_con= new SqlConnection(ConnectionString);
m_con.Open();
MessageBox.Show("数据库连接成功!");
flag=true;
}
catch
{
MessageBox.Show("数据库连接不成功!");
flag=false;
}
returnflag;
}
(一)、c#连接SQL数据库代码:==只是一个简单的例子
publicDataTable Read()
{
DataTabledt =new DataTable();//新建表
dt.Columns.Add("col_1");//新建表中的列
dt.Columns.Add("col_2");
stringConnectionString ="data source=localhost;initial catalog=pubs;userid=sa;password=sa";
SqlConnection Conn=new SqlConnection(ConnectionString);
if(Conn.State==ConnectionState.Open)
{
Conn.Close();
}
Conn.ConnectionString=ConnectionString;
Conn.Open();
try
{
SqlCommandcmd=new SqlCommand("Select * from tab_name",Conn);
SqlDataReadermyReader =cmd.ExecuteReader();//执行SQL语句的真正查询了
inta=0;
intb=0;//用来接收已经查询出来的字段
while(myReader.Read()) 每次循环查到的一行 如果有N行就循环N次而已
{
DataRowdr =dt.NewRow();//每循环一次新建一行
dr[0]=myReader.GetInt32(0).ToString(); 表示接收第一个字段(string型)
dr[1] =myReader.GetInt32(1).ToString();
dt.Rows.Add(dr);//每次循环把dr加进去
}
myReader.Close();
Conn.Close();
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message.ToString());
}
returndt;
}
(二)、 关于Command对象 (SqlCommand有两种方法各有优点)
//只用于查询其实可以用于多记录查询 两个SQL语句连起来 用 myReader.NextResult() 即可
(A)SqlCommand cmd =new SqlCommand(SqlText,con);//这是读数据 此要和 SqlDataReader连用 再和ExecuteReader或ExecuteScalar连用.
new 这个是用来读数据的 就用DataReader 来接
这句等同于下面的三句
(B)
//这个不用于查询用于执行T_SQL增删改等等
SqlCommandcmd =con.CreateCommand();
cmd.CommandTest="Createtable tab_name (name varchar(20),password varchar(20))";
cmd.ExecuteNonQuery();
***说明 :关于SqlCommand用法有ExecuteNonQuery、ExecuteReader,ExecuteScalar三种其中ExecuteReader(所有查询),ExecuteScalar(首行首列查询)
ExecuteNonQuery为执行T-SQL语句但是不建议查询
如果一个类有多个SQL语句要执行用(B)ExecuteNonQuery三句 但是ExecuteNonQuery自动执行最靠近它的那句CommandTest(每次只执行一句)
如果一个类中只有一个SQL语句要执行用(A)即可
***说明: (A)A与ExecuteReader,ExecuteScalar相匹配
(B)B三句的与ExecuteNonQuery相匹配
(三)、关于数据读取器 SqlDataReader 对象 (其中SqlDataReader是和SqlCommand cmd =new SqlCommand(SqlText,con)它连用的)
如果只想读取和显示数据 则只需使用数据读取器 SqlDataReader即可 但要处理数据然后更新数据库,就需要用数据集DataSet和适配器 SqlDataAdaper
SqlDataReader reader =new SqlDataReader();
(A)实例:
SqlCommandcmd=new SqlCommand("Select * from tab_name",Conn);
SqlDataReadermyReader =cmd.ExecuteReader();//执行SQL语句的真正查询了
while(myReader.Read()) 每次循环查到的一行 如果有N行就循环N次而已
{
DataRowdr =dt.NewRow();//每循环一次新建一行
dr[0]=myReader.GetInt32(0).ToString(); 表示接收第一个字段(string型)
dr[1] =myReader.GetInt32(1).ToString();
dt.Rows.Add(dr);//每次循环把dr加进去
(B):GetSchemaTable方法 返回一个已填充的DataTable实例 (可以一次读出完整表的内容)
DataTableschema =reader.GetSchemaTable();
用它可以把数据库中查询出的结果集以表的形式得到完整的传给schema表
就可以通过DataTable的Rows属性检索行集,通过DataTable的Columns属性检索列集(Rows属性可用于给表添加新行或者从表中删除行,
Columns属性可用于添加列或者删除现有的列)
实例:
DataTableschema =reader.GetSchemaTable();//查询出的结果集以表的形式得到完整的传给schema表
foreach(DataRow row in schema.Rows)//这时相当于对schema表进行操作了
{
foreach(DataColumn col in schema.Columns)
{
Console.WriteLine(col.ColumnName+ "=" + row[col]);
Console.WriteLine("==========");
}
}
(C):reader.NextResult() 使用数据读取器处理多个结果集
string sql_1=@"select * from tab_1";
string sql_2=@" select * fromtab_2";//这里一定要有个空格才可以 因为当两个SQL语句连接时要用空格分开
string sql =sql_1 + sql_2;
SqlCommand cmd =new SqlCommand(sql,con);//执行两个或多个SQL语句的联合查询
SqlDataReader reader=cmd.ExecuteReader();//这时有多个结果集
do
{
while(reader.Read())//读取一个结果集的所有内容
{
Console.WriteLine("{0}:{1}",reader[0],reader[1]);
}
Console.WriteLine("".PadLeft(60,'='));
}
while(reader.NextResult());//循环读下个结果集
***补充:如果想判断当SqlDataReader没有读出结果时要做的处理方法:
首先要走
while(reader.Read())//读取一个结果集的所有内容
{
Console.WriteLine("{0}:{1}",reader[0],reader[1]);
}
中的reader.Read();//必须要走这一步
如果想判断当没有读出结果时 就必须在While(reader.Read())之后
if(reader.HasRows==false)//判断如果没有读出结果
{
MessageBox.Show("要查询的结果不存在!");
}
这是没有读出结果时 如果读出结果了 那就直接走while(reader.Read()){}里面了就不走if(){}里面了
其实如果用到了DataTable 也可以用if(dt.Rows.count<0){}也可以的
[SqlDataAdapter]
(四)、SqlDataAdapter
数据集和数据适配器 DataSet 和 SqlDataAdapter
知识点:
SqlDataAdapter da =new SqlDataAdapter();
(1)da.Fill();
(2)da.SelectComand=newSqlCommand(sqlText,con);
(3)DataTabledt=new DataTable();
dt.Select(where条件,升降序);
(4)
填充数据集有两种方法:
:使用数据适配器
:从XML文档中读取数据
4.1)
SqlDataAdapter da =new SqlDataAdapter();
da.SelectCommand =new SqlCommand(sqlText,con);
DataSet ds =new DataSet();
da.Fill(ds,"tab_name");//Fill方法内部使用数据读取器访问表模式和数据,然后使用他们填充数据集
//相当于执行SQL语句后把结果集取出后赋给DataSet中的tab_name表。
4.2)
数据集的筛选和排序:例子
staticvoid Main(string [] args)
{
stringConnectionString =@"data source=localhost;initial catalog=northwind;userid =sa;password=sa;";
stringsql_1=@"select * from customers";
stringsql_2=@" select * from products where unitprice <10";//注意当第二句连接时要有个空格
stringsql = sql_1+sql_2;//两条SQL语句拼接
SqlConnectioncon =new SqlConnection(ConnectionString);
if(con.State==ConnectionState.Open)
{
con.Close();
}
try
{
con.Open();
SqlDataAdapterda=new SqlDataAdapter();//A
da.SelectCommand=newSqlCommand(sql,con);//B
//其中A和B两句合并相当于:SqlDataAdapterda=new SqlDataAdapter(sql,con);这一句
DataSetds=new DataSet();
da.Fill(ds,"customers");
DataTableCollectiondtc =ds.Tables;//通过这句把DataSet中的所有表都给了Table表集合
Console.WriteLine("Resultsfrm Customers table:");
Console.WriteLine("CompanyName".PadRight(20)+ "ContactName".PadLeft(23) + "\n");
//以下两句是筛选条件
stringfl ="country='Germany'";//where 条件
stringsrt ="companyname asc"; //降序
//下面是知识点 数据集的筛选条件
foreach(DataRowrow in dtc["customers"].Select(fl,srt))//这是用法
//dtc["customers"]说明:dtc表集合中的customers表 .Select() 就是筛选条件
{
Console.WriteLine("{0}\t{1}",row["CompanyName"].ToString().PadRight(25),row["ContactName"]);
}
Console.WriteLine("\n----------------------------");
Console.WriteLine("Resultsform Products table:");
Console.WriteLine("ProductName".PadRight(20)+ "UnitPrice".PadLeft(21) + "\n");
foreach(DataRowrow in dtc[1].Rows)
{
Console.WriteLine("{0}\t{1}",row["productname"].ToString().PadRight(25),row["unitprice"]);
}
Console.ReadLine();
}
catch(Exceptionex)
{
Console.WriteLine("Error:"+ex);
Console.ReadLine();
}
finally
{
con.Close();
}
}
4.3)
使用DataView 其实DataView 的功能4.2)数据集都可以实现 所以一般不常用
DatView是DataTable内容的动态表示,与SQL视图一样,他不保存数据
下面一句就是把dt表中的记录有赋给了DataView dv 然后对dv进行操作 DataView有自己的动态方法
DataViewdv =new DataView(dt,"country='Germany'","country",DataViewRowState.CurrentRows);
例子:
static void Main(string[]args)
{
stringConnectionString =@"data source =localhost;initial catalog =northwind;userid =sa;password=sa;";
stringsqlText=@"select contactname,country from customers";
SqlConnectioncon =new SqlConnection(ConnectionString);
if(con.State==ConnectionState.Open)
{
con.Close();
}
try
{
SqlDataAdapterda =new SqlDataAdapter(sqlText,con);
//da.SelectCommand=new SqlCommand(sqlText,con);
DataSetds=new DataSet();
da.Fill(ds,"customers");//填充给DataSet中的Customeres表
DataTabledt=ds.Tables["customers"];
//下面一句就是把dt表中的记录有赋给了DataView dv 然后对dv进行操作 DataView有自己的动态方法
DataViewdv =new DataView(dt,"country='Germany'","country",DataViewRowState.CurrentRows);
//其中第一个参数是DataTale,第二个是对DataTable内容进行筛选的筛选器,第三个是排序,最后一个参数指定要在视图中包含的行的类型
foreach(DataRowViewdrv in dv)
{
for(inti=0;i<dv.Table.Columns.Count;i++)
{
Console.Write(drv[i]+ "\t");
}
Console.WriteLine();
}
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error:"+ ex);
}
finally
{
con.Close();
}
}
4.4)修改数据集中的记录 其实这个4.4)单独是没有意义的 应该是4.5以后将更新保存到数据库源
说明:对数据集所做的变化不会自动保存到数据库中,为了把这些变化保存到数据库中,需要再次连接数据库,显示完成更新
例子:
staticvoid Main()
{
stringConnetionString=@"data source=localhost;initial catalog=northwind;user id=sa;password=sa;";
stringqry=@"select * from employees where country='UK'";
stringudp=@"update employees set city=@city where employeeid=@employeeid";
SqlConnection con =newSqlConnection(ConnetionString);
try
{
SqlDataAdapterda= new SqlDataAdapter();
da.SelectCommand=new SqlCommand(qry,con);
DataSetds=new DataSet();
da.Fill(ds,"employees");
DataTabledt=ds.Tables["employees"];
//以下更改了表的信息
dt.Columns["FirstName"].AllowDBNull=true;
dt.Rows[0]["city"]="Wilmington";
//以下为表添加了新行
DataRownewRow =dt.NewRow();
newRow["firstname"]="li";
newRow["lastname"]="yong";
newRow["titleofcourtesy"]="haha";
newRow["city"]="dalian";
newRow["country"]="UK";
dt.Rows.Add(newRow);
//可以显示更新后的信息 这时只更新了数据集 但是没有更新数据库
foreach(DataRowrow in dt.Rows)
{
Console.WriteLine("{0}{1}{2}",row["firstname"].ToString().PadRight(15),row["lastname"].ToString().PadLeft(25),row["city"]);
}
Console.ReadLine();
}
catch(Exceptionex)
{
Console.WriteLine("Error:"+ ex);
}
finally
{
con.Close();
}、
4.5)将变化保存到数据源
以下3个属性可用于把数据集中的数据更新和同步到数据源(类似于支持查询的SelectCommand属性)
*UpdateCommand
*InsertCommand
*DeleteCommand
***A)UpdateCommand属性
SqlDataAdapterda =new SqlDataAdapter();
要想对数据库进行修改要是动态的必须有参数
//以下这是第二次操作数据库(用SqlCommand)进行更改
SqlCommandcmd=new SqlCommand(upd,conn);//udp为SQL语句 它是有参数的
cmd.Parameters.Add("@city",SqlDbType.NVarChar,15,"city");//为upd语句设定两个参数
cmd.Parameters.Add("@employeeid",SqlDbType.Int,4,"employeeid");
da.UpdateCommand=cmd;
da.Update(ds,"表名");
staticvoid Main()
{
stringConnectionString =@"data source =localhost;initial catalog=northwind;userid =sa;password=sa;";
stringqry=@"select * from employees where country='UK'";//用于从库中取出数据进行更改用的SQL
stringupd=@"update employees set city=@city where employeeid=@employeeid";//更改的SQL
SqlConnectionconn =new SqlConnection(ConnectionString);
try
{
SqlDataAdapterda =new SqlDataAdapter();
da.SelectCommand=newSqlCommand(qry,conn);
DataSet ds=new DataSet();
da.Fill(ds,"employees");
DataTabledt=ds.Tables["employees"];
(a)dt.Rows[0]["city"]="Wilmington11";//改后的信息 其实是SQL update语句的参数
//以下只是数据集做了更改后显示出来
foreach(DataRowrow in dt.Rows)
{
Console.WriteLine("{0}{1}{2}",row["firstname"].ToString().PadRight(15),row["lastname"].ToString().PadLeft(25),row["city"]);
}
//这以下才是对数据库进行的真正更改
SqlCommandcmd=new SqlCommand(upd,conn);//udp为SQL语句 它的参数是(a)
//设定两个参数
cmd.Parameters.Add("@city",SqlDbType.NVarChar,15,"city");
cmd.Parameters.Add("@employeeid",SqlDbType.Int,4,"employeeid");
da.UpdateCommand=cmd;//修改赋值
da.Update(ds,"employees");//修改
}
catch(Exceptionex)
{
Console.WriteLine("Error:"+ex);
}
***B)InsertCommand属性
数据适配器使用InsertCommand属性在表中插入行,调用Update方法时,将搜索以前添加到表中的说有新行,并保存到数据库中。
staticvoid Main()
{
stringConnectionString =@"data source=localhost;initial catalog=northwind;userid =sa;password=sa";
stringqry=@"select * from employees where country='UK'"; //第一步 从库中取数据SQL语句
stringins=@"
insertinto employees(firstname,lastname,titleofcourtesy,city,country) //第二步SQL更改语句
values
(
@firstname,
@lastname,
@titleofcourtesy,
@city,
@country
)
";
SqlConnectionconn =new SqlConnection(ConnectionString);
try
{
SqlDataAdapterda=new SqlDataAdapter();
da.SelectCommand=newSqlCommand(qry,conn);
DataSetds =new DataSet();
da.Fill(ds,"employees");
DataTabledt=ds.Tables["employees"];//已把原库中的数据赋值给了dt
DataRownewRow =dt.NewRow();
//以下添加的每列新行就是 下面参数的要赋的新值
newRow["firstname"]="li";
newRow["lastname"]="yong";
newRow["titleofcourtesy"]="Sir";
newRow["city"]="Birmingham";
newRow["country"]="UK";
dt.Rows.Add(newRow);//然后为dt添加一个新行
foreach(DataRowrow in dt.Rows)//把现在的结果遍例出来
{
Console.WriteLine("{0}{1}{2}",
row["firstname"].ToString().PadRight(15),
row["lastname"].ToString().PadLeft(25),
row["city"].ToString().PadLeft(35)
);
}
SqlCommandcmd =new SqlCommand(ins,conn);//传递InsertCommand SQL更改命令
//以下是设定InsertCommand参数
cmd.Parameters.Add("@firstname",SqlDbType.NVarChar,10,"firstname");
cmd.Parameters.Add("@lastname",SqlDbType.NVarChar,20,"lastname");
cmd.Parameters.Add("@titleofcourtesy",SqlDbType.NVarChar,25,"titleofcourtesy");
cmd.Parameters.Add("@city",SqlDbType.NVarChar,15,"city");
cmd.Parameters.Add("@country",SqlDbType.NVarChar,15,"country");
以下两句是真正的更改数据库
da.InsertCommand=cmd;
da.Update(ds,"employees");
Console.ReadLine();
}
catch(Exceptionex)
{
Console.WriteLine("Error:"+ex);
Console.ReadLine();
}
finally
{
conn.Close();
}
}
***C)DeleteCommand属性
DeleteCommand属性可用于执行SQLDELETE语句。
staticvoid Main()
{
stringConnectionString =@"data source =localhost;initial catalog=northwind;userid =sa;password=sa;";
stringqry=@"select * from employees where country='UK'";//第一步 从库中取数据SQL语句
stringdel=@"delete from employees where employeeid =@employeeid"; //第二步SQL更改语句
SqlConnectioncon=new SqlConnection(ConnectionString);
try
{
//注释: 虽然这段代码用的delete语句用到了参数whereemployeeid =@employeeid
//但是在下面又用到了filt 筛选条件 所以明确了用名字来判断 那么where employeeid =@employeeid就没有意义了
SqlDataAdapterda=new SqlDataAdapter();
da.SelectCommand=new SqlCommand(qry,con);
DataSetds=new DataSet();
da.Fill(ds,"employees");
DataTabledt =ds.Tables["employees"]; //把原来的数据库中数据提取出来赋给dt
SqlCommandcmd=new SqlCommand(del,con); //传递DeleteCommand SQL更改命令
cmd.Parameters.Add("@employeeid",SqlDbType.Int,4,"employeeid"); //为DeleteCommand添加参数
stringfilt=@"firstname='li' and lastname='yong'";//筛选条件
foreach(DataRowrow in dt.Select(filt))
{
row.Delete();
}
//以下两句真正删除数据
da.DeleteCommand=cmd;
da.Update(ds,"employees");
//把现在的结果集遍例出来
foreach(DataRowrow in dt.Rows)
{
Console.WriteLine("{0}{1}{2}",row["firstname"].ToString().PadRight(15),row["lastname"].ToString().PadLeft(25),row["city"]);
}
Console.ReadLine();
}
catch(Exceptionex)
{
Console.WriteLine("Error:"+ ex);
}
finally
{
con.Close();
}
}
五) 关于DataRowView 的用法(此时要想得到listBox选中的数据(前提是把数据库中的数据赋给listBox))
DataRowViewrowView=(DataRowView)this.listBox1.Items[this.listBox1.SelectedIndex];
stringstr=rowView.Row.ItemArray[0].ToString();
MessageBox.Show("您选择的是:"+str,"***这种方法只能这样写代码,请看看");
***详见级联菜单的例子
用以下的cmd命令可以创建一个新的iis站点:
C:\Inetpub\AdminScripts> adsutil.vbscreate_vserv W3SVC/2
C:\Inetpub\AdminScripts> adsutil.vbscopy W3SVC/1 W3SVC/2
删除:
C:\Inetpub\AdminScripts> adsutil.vbsdelete W3SVC/2
List:
C:\Inetpub\AdminScripts> adsutil.vbsenum w3svc /p
当然,创建了以后也只能同时运行一个。
========