首页 > 代码库 > ADO.NET学习笔记-读写数据
ADO.NET学习笔记-读写数据
1. DbCommand对象
要读写数据,一是需要有效的数据链接,二是需要DbCommand对象向数据源传递SQL命令。DbCommand对象包含的命令可以是DML数据操作语言,也可以是DDL数据定义语言。创建DbCommand的最好方式是先创建DbConnection,然后使用DbConnection的CreateCommand()方法,这样创建的DbCommand与DbConnection之间最为匹配。DbCommand必备的两个重要属性为CommandText和CommandType,示例代码如下:
static void Main()
{
var conString = ConfigurationManager.ConnectionStrings["TestApp.Properties.Settings.toucaiConnectionString"].ConnectionString;
var conn = new MySqlConnection(conString);
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select count(*) from product";
conn.Open();
long count = (long)cmd.ExecuteScalar();
Console.WriteLine("共有" + count + "条商品条记录");
conn.Close();
}
2. DbParameter对象
如果CommandType属性的值为CommandType.Procedure,则多半需要使用DbParameter对象,因为大部分的SQL过程都需要输入或输出参数。例如如果服务器上有过程product_name,其代码如下:
CREATE DEFINER=`lqs2011`@`%` PROCEDURE `product_name`(
IN oPrice DECIMAL(8, 2)
)
BEGIN
SELECT prodName, outPrice
FROM product
WHERE outPrice = oPrice AND brandID = 1;
END
可以看出此过程要求一个输入参数oPrice,用于指定零售价格,示例程序如下:
using (var conn = new MySqlConnection(conString))
{
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "product_name";
var param = cmd.CreateParameter();
param.ParameterName = "@oPrice";
param.Value = "398.00";
cmd.Parameters.Add(param);
conn.Open();
var reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("{0,-15}\t{1,15}", reader[0], reader[1]);
}
}
需要注意的是,不同的数据提供程序(Provider)对参数的要求不同,例如SQL SERVER要求参数的名称必须与数据库过程中的名称一致,于是顺序就不重要了;而OLEDB则要求参数的顺序必须与数据库过程中的参数相一致,于是参数名称就不重要了。为满足不同数据提供程序的要求,我们最好名称及顺序都与数据库过程保持一致。
3. DbCommand的执法
常用的命令执法方法有ExecuteNonQuery()、ExecuteReader()和ExecuteScalar()三种,其中:
- ExecuteNonQuery()顾名思义是执法非查询语句的,例如用DDL语言来创建、更改或删除数据库对象等,此方法不会返回数据行,但会返回一个整形数据,用于显示受影响的行的数目。
- ExecuteReader()方法返回一个DbDataReader实例,这是一个只读只进的,存在于服务器端的指针。第2条中的代码已经演示了此方法的执法过程。
- ExecuteScalar()方法返回首行首列的值,一般也只有一行一列,即返回一个标题值,而非一个列对象。如前面的
long count = (long)cmd.ExecuteScalar()
cmd.ExecuteScalar()返回的是一个object对象,装箱后成为一个长整形值。在需要返回一个确定的值时,使用此方法可大幅提升性能。
4. DbDataReader对象
前面已经提到,DbDataReader是一个只读只进的,存在于服务器端的指针,性能非常优异,常用于填充ListBox、DropDownList等控件数据。在运行报表时,也可使用此对象来获取远程服务器端的数据来显示。当然,因为此对象得到的数据是只读的,所以如果需要修改数据并将修改后的数据回写到远程数据库,就不能再用DbDataReader对象了,而应使用DbDataAdapter对象。
DbDataReader最主要的方法为Read(),用于将远程数据加载至此对象的缓冲中。示例代码如下:
using (var conn = new MySqlConnection(conString))
{
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT prodName, outPrice FROM product";
conn.Open();
var reader = cmd.ExecuteReader();
var tbProducts = new DataTable();
tbProducts.Load(reader, LoadOption.Upsert);
cmbProducts.DataSource = tbProducts;
cmbProducts.DisplayMember = "prodName";
cmbProducts.ValueMember = "prodName";
}
注意,在使用DataTable加载数据时,有一个加载选项,即LoadOption枚举类型,用于定义本地数据与远程数据不一致时的行为,共有3个值,分别为:
- OverwriteChanges:放弃本地更改
- PreserveChanges:保留本地更改
- Upsert:目的是从远程下载数据,以远程数据为主
5. DbDataAdapter对象
此对象是ADO.NET进行数据同步的核心对象,用于在本地数据和远程数据源间进行数据同步。在获取数据时,DbDataAdapter拥有一个SelectCommand属性,SelectCommand属性又有一个合法的DbCommand对象,这个DbCommand对象又有一个合法可用的数据链接。DbCommand对象又有一个ExecuteReader方法,执法后得到一个DbDataReader对象,用于填充DataTable对象。
DbDataAdapter还拥有InsertCommand, UpdateCommand和DeleteCommand属性,它们均可能包含DbCommand对象,如果仅仅是从远程数据源读取数据而不做任何更改并回传同步,则不必创建这些属性,但如果需要更改并回传数据,则需同时创建上述4种命令(含SelectCommand)。
DbDataAdapter在进行数据同步前会检查数据链接情况,如果链接没有打开,就自动打开链接,完成工作后自动关闭链接,但还是建议手动打开并关闭链接,一是有良好的习惯,二是在同时有多个DbDataAdapter工作时,手动打开链接能提升性能。
6. 使用DbDataAdapter的Fill()方法
此方法用于将远程DataSet数据填充到本地DataTable对象。示例代码如下:
using (var conn = new MySqlConnection(conString))
{
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT prodName, outPrice FROM product"; //初始化SelectCommand
conn.Open();
var da = new MySqlDataAdapter(cmd);
var ds = new DataSet();
da.Fill(ds, "product"); //用于将远程product表中的数据填充至本地DataSet中
cmbProducts.DataSource = ds.Tables[0];
cmbProducts.DisplayMember = "prodName";
}
编程建议,如果需回传修改后的数据,最好为每个DataTable创建单独的DataAdapter,如果不需回传数据,则使用DbDataReader就够了。
7. 使用update()方法保存修改至远程数据源
update()方法保存修改至远程数据源的过程如下:
- 从本地DataTable中找出更改内容
- 使用InsertCommand, UpdateCommand或是DeleteCommand在远程数据源中执行更改
- 执行更改是按行进行的(on a row-byrow basis)
- update()方法判断行是否被更改的依据是查看行的RowState属性,如果行属性不为Unchanged,则执行更改
- 手工分别创建DbCommand对象(一般不用)
- 使用DataAdapter配置向导(DataAdapter Configuration Wizard,在向窗体中添加DataAdapter时自动打开)
- 使用DbCommandBuilder对象,但需要DataAdapter有一个合法可用的SelectCommand对象
using (var conn = new MySqlConnection(conString))
{
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM product";
var da = new MySqlDataAdapter(cmd);
var ds = new DataSet();
var cmdBuilder = new MySqlCommandBuilder(da);
conn.Open();
da.Fill(ds, "product");
var dt = ds.Tables[0];
var updateRow = dt.Select("innerBar = ‘ZZZ002‘")[0];
updateRow["outPrice"] = (decimal)8.0;
int count = da.Update(ds, ds.Tables[0].TableName);
if(count > 0)
Console.WriteLine("OK");
}
8. 打包提交更改至远程数据库
系统默认是逐个向远程数据库提交更改,通过设置DataAdapter的UpdateBatchSize属性值为0可让系统将尽可能多的数据行打包提交,从而大幅提升性能。9. DbProviderFactory类
到目前为止,我们看到的代码都是与具体的provider相关联的,比如MySqlConnection对象,是由MySQL Provider提供的,于是也只能用于连接MySQL数据库,要实现代码与具体的远程数据源类型无关的代码,需用到DbProviderFactory类。
ADO.NET学习笔记-读写数据
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。