在代码中使用SqlCommand对象

(2009-09-21 11:16:10)

转载
  分类:.Net编程类

1.1  创建SqlCommand对象

可以通过三种方式创建SqlCommand对象。第一种方式就是使用new关键字直接创建对象的一个新实例,然后设置适当属性;还可以使用一个可用的构造函数来指定查询字符串以及 SqlConnection对象;第三种方式是调用SqlConnection类(第3章对这个类进行了介绍)的CreaterCommand方法。这三种方法如下所示:

string strConn, strSQL;

strConn = @"Data Source=./SQLExpress;" +

"Initial Catalog=Northwind;Trusted_Connection=Yes;";

strSQL = "SELECT CustomerID, CompanyName FROM Customers";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

SqlCommand cmd;

//使用无参数构造函数

cmd = new SqlCommand();

cmd.Connection = cn;

cmd.CommandText = strSQL;

//使用参数化构造函数

cmd = new SqlCommand(strSQL, cn);

//使用Connection对象的CreateCommand方法

cmd = cn.CreateCommand();

cmd.CommandText = strSQL;

1.2  使用SqlCommand执行查询

了解了如何创建SqlCommand对象,下面介绍使用SqlCommand执行查询的基本情况。

1.3  执行返回行的查询

SqlCommand的最常见用法是执行返回结果的查询。例如要获取一特定国家(可能是加拿大)发货订单的信息,可以使用如下所示的查询:

SELECT OrderID, CustomerID, OrderDate, ShippedDate, ShipCity

FROM Orders WHERE ShipCountry = 'Canada'

要执行此查询,首先需要将SqlCommand对象的CommandText属性设置为包含该查询文本的一个字符串。然后调用SqlCommand对象的ExecuteReader方法,如以下代码所示:

string strConn, strSQL;

strConn = @"Data Source=./SQLExpress;" +

"Initial Catalog=Northwind;Trusted_Connection=Yes;";

strSQL = "SELECT OrderID, CustomerID, OrderDate, ShippedDate, ShipCity" +

" FROM Orders WHERE ShipCountry = 'Canada'";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

SqlCommand cmd = cn.CreateCommand();

cmd.CommandText = strSQL;

SqlDataReader rdr = cmd.ExecuteReader();

1.4  获取单一值

在某些时候,可能希望执行一个返回单一值的查询。例如执行一个简单查询,以确定在一个表中存在多少行,或者更复杂一些,如确定一个特定客户所下订单的总数是多少,可以使用类似于以下代码的查询:

SELECT SUM([Order Details].UnitPrice * [Order Details].Quantity)

FROM Orders INNER JOIN [Order Details]

ON Orders.OrderID = [Order Details].OrderID

WHERE Orders.CustomerID = 'ALFKI'

诸如此类的查询在许多应用程序中都很常见。以下代码段执行此查询,并将订单总值输出到控制台窗口。其中,创建一个SqlDataReader、调用Read、检查第一行第一列的内容,然后再关闭

string strConn, strSQL;

strConn = @"Data Source=./SQLExpress;" +

"Initial Catalog=Northwind;Trusted_Connection=Yes;";

strSQL = "SELECT SUM(UnitPrice * Quantity) " +

" FROM Orders INNER JOIN [Order Details]" +

" ON Orders.OrderID = [Order Details].OrderID" +

" WHERE CustomerID = 'ALFKI'";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

SqlCommand cmd = new SqlCommand(strSQL, cn);

SqlDataReader rdr = cmd.ExecuteReader();

rdr.Read();

decimal decOrderTotal = (decimal)rdr[0];

rdr.Close();

Console.WriteLine("Order Total: {0:c}", decOrderTotal);

为了帮助简化此类情况,SqlCommand类公开了一个ExecuteScalar方法。ExecuteScalar方法不是返回一个SqlDataReader,而是返回在一般Object数据类型中第一行第一列的值。此类方法通常称为“syntactic sugar”(语法甜头),至少在我工作的地方是这样称呼它的。换言之,调用ExecuteScalar有效地创建了一个SqlDataReader,并获取期望信息,但不需要编写全部代码。然后,ExecuteScalar关闭并处置SqlDataReader。

string strConn, strSQL;

strConn = @"Data Source=./SQLExpress;" +

"Initial Catalog=Northwind;Trusted_Connection=Yes;";

strSQL = "SELECT SUM(UnitPrice * Quantity) " +

" FROM Orders INNER JOIN [Order Details]" +

" ON Orders.OrderID = [Order Details].OrderID" +

" WHERE CustomerID = 'ALFKI'";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

SqlCommand cmd = new SqlCommand(strSQL, cn);

decimal decOrderTotal = (decimal)cmd.ExecuteScalar();

Console.WriteLine("Order Total: {0:c}", decOrderTotal);

1.5  执行不返回结果集的查询

不返回结果集的查询通常被称为“操作查询(action query)”,在本书中有时会使用这一术语。操作查询共有两大类。

l   数据操作语言(DML)查询  也称为“基于查询的更新(QBU)”,这些查询修改数据库的内容。下面是一些例子:

INSERT INTO Customers (CustomerID, CompanyName)

VALUES ('NewID', 'NewCustomer')

UPDATE Customers SET CompanyName = 'NewCompanyName'

WHERE CustomerID = 'ALFKI'

DELETE FROM Customers WHERE CustomerID = 'ALFKI'

l   数据定义语言(DDL)查询  这些查询修改数据库的结构,如下例所示:

CREATE TABLE Table1 (Field1 int NOT NULL

CONSTRAINT PK_Table1 PRIMARY KEY,

Field2 varchar(32))

ALTER VIEW View1 AS SELECT Field1, Field2 FROM Table1

DROP PROCEDURE StoredProcedure1

可以通过调用SqlCommand的 ExecuteReader方法来执行这些查询。但是,因为这些查询不返回任何行,所以似乎是一些不必要的开销。幸运的是,还有更简单的方法。 SqlCommand类公开了ExecuteNonQuery方法,该方法执行查询而不返回SqlDataReader对象。下面的例子说明如何使用这一特性。

string strConn, strSQL;

strConn = @"Data Source=./SQLExpress;" +

"Initial Catalog=Northwind;Trusted_Connection=Yes;";

strSQL = "UPDATE Customers SET CompanyName = 'NewValue' " +

"WHERE CustomerID = 'ALFKI'";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

SqlCommand cmd = new SqlCommand(strSQL, cn);

//cmd.ExecuteNonQuery();

int intRecordsAffected = cmd.ExecuteNonQuery();

if (intRecordsAffected == 1)

Console.WriteLine("Update succeeded");

else

//Assume intRecordsAffected = 0

Console.WriteLine("Update failed");

1.6  执行批量操作查询

假定您希望成批执行一系列操作查询。例如,假定有一个Products表,并希望根据产品目录改变一些产品的单价,一些标为涨价,一些标为降价。可以将以下查询放在一起,然后同时执行它们。

UPDATE Products SET UnitPrice = UnitPrice * 0.85 WHERE CategoryID = 3;

UPDATE Products SET UnitPrice = UnitPrice * 1.15 WHERE CategoryID = 4;

UPDATE Products SET UnitPrice = UnitPrice * 0.75 WHERE CategoryID = 5;

如果希望知道每个查询影响了多少行,应当怎么办呢?理想情况下,可能会调用一个简单的方法,例如ExecuteNonQuery,使此方法返回一个值的数组,其中,数组的项对应于由批处理中各个查询所修改的行数。

ExecuteReader和ExecuteNonQuery方法都不能独自完成此功能。这两种方法都允许执行批量查询,但都不能告知每个查询所修改的行数。ExecuteNonQuery方法的返回值将告知整个批处理修改了多少行,但这一信息也许不能满足您的需要。

ADO.NET 2.0中的(新的和)经过改进的SqlCommand公开了一个StatementCompleted事件,可以用来收集这一信息。 StatementCompleted事件的主要参数拥有唯一一个很有意义的属性RecordCount,但是幸运的是,这就是我们要寻找的信息。以下代码段说明可以如何使用这一事件来确定批量操作中各个查询所修改的行数。此代码包括一个处理StatementCompleted事件的过程。如果正在复制和粘贴此代码,则需要单独粘贴该过程。

string strConn, strSQL;

strConn = @"Data Source=./SQLExpress;" +

"Initial Catalog=Northwind;Trusted_Connection=Yes;";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

strSQL = "UPDATE Products SET UnitPrice = UnitPrice * 0.85 " +

" WHERE CategoryID = 3;" +

"UPDATE Products SET UnitPrice = UnitPrice * 1.15 " +

" WHERE CategoryID = 4;" +

"UPDATE Products SET UnitPrice = UnitPrice * 0.75 " +

" WHERE CategoryID = 5;";

SqlCommand cmd = new SqlCommand(strSQL, cn);

cmd.StatementCompleted +=

new StatementCompletedEventHandler(HandleStatementCompleted);

int intTotalRowsAffected = cmd.ExecuteNonQuery();

Console.WriteLine("TotalRowsAffected: {0} row(s)", intTotalRowsAffected);

cn.Close();

...

static void HandleStatementCompleted(object sender,

StatementCompletedEventArgs e) {

Console.WriteLine("Statement Affected {0} row(s)", e.RecordCount);

}

1.7  执行获取XML数据的查询

SQL Server支持以XML形式返回数据的查询。如果正在使用这种类型的查询,可以调用SqlCommand的ExecuteXmlReader方法,以通过XmlReader来获得结果,而不是通过SqlDataReader。在第12章中将更详细地研究这一情景。

1.8  在事务中执行查询

SqlCommand类拥有一个 Transaction属性,必须对其进行设置以在SqlTransaction中执行SqlCommand。在上一章中,已经了解了如何使用 SqlConnection类的BeginTransaction方法创建SqlTransaction对象。

如果开始了SqlConnection的一个 SqlTransaction,必须将所有查询与该事务相关联。否则,将会接收到一个InvalidOperationException,同时带有一条消息指出:“当分配给该命令的连接处于挂起的本地事务中时,ExecuteNonQuery要求该命令拥有一个事务。该命令的Transaction属性未被初始化。”

有两种方式可以将SqlCommand与 SqlTransaction关联在一起。可以将SqlCommand的Transaction属性设置为SqlTransaction,也可以将 SqlTransaction传递给SqlCommand的构造函数。以下代码使用第二种方法。在执行查询并确定该查询影响多少行之后,该代码调用 SqlTransaction的Rollback方法,以防止数据库提交这些更改。

string strConn, strSQL;

strConn = @"Data Source=./SQLExpress;" +

"Initial Catalog=Northwind;Trusted_Connection=Yes;";

strSQL = "UPDATE Products SET UnitPrice = UnitPrice * .7 " +

" WHERE CategoryID = 1";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

using (SqlTransaction txn = cn.BeginTransaction()) {

SqlCommand cmd = new SqlCommand(strSQL, cn, txn);

int intRecordsAffected = cmd.ExecuteNonQuery();

Console.WriteLine("Query affected {0} row(s)", intRecordsAffected);

txn.Rollback();

}

cn.Close();

 提示    为了确保没有使事务开放太长时间,请考虑在Using代码块中使用SqlTransaction对象,如以上代码段所示。事务保持开放的时间越长,数据库需要为该事务维护锁的时间也就越长,多位用户尝试锁定相同行的机会也就越大。如果在Using代码块的末尾没有提交或回滚SqlTransaction,则会隐式调用Rollback方法。

在代码中使用SqlCommand对象相关推荐

  1. selenium代码中创建浏览器对象_Sinno_Song_新浪博客

    一.直接将chromedriver.exe放置在python.exe的同目录下,代码中可以直接写为: driver= webdriver.Chrome() 二.将chromedriver.exe放置在 ...

  2. 关于代码中生成HSSFWorkbook对象,转换成输入流,上传到服务器.下载的xls文件打开报错问题

    今天在做项目开发是遇到一个问题,就是在java代码中创建HSSFWorkbook表格写入数据后,不直接返回给前端下载,而是上传到服务器: 开始直接通过 InputStream is = new Byt ...

  3. 数据库-ADONET-在数据集DataSet中使用关系对象DataRelation处理关系

    处理关系数据 数据库中,表很少是独立结构的,大部分数据库都包含相互关联的表. 在构建应用程序时,会遇到--显示或者通过程序设计访问数据库中相关表的数据的情况. 用户会希望,能通过在不同的表之间定位,来 ...

  4. java map 结构体_业务代码的救星——Java 对象转换框架 MapStruct 妙用

    简介 在业务项目的开发中,我们经常需要将 Java 对象进行转换,比如从将外部微服务得到的对象转换为本域的业务对象 domain object,将 domain object 转为数据持久层的 dat ...

  5. 定义一个dto对象_业务代码的救星——Java 对象转换框架 MapStruct 妙用

    在业务项目的开发中,我们经常需要将 Java 对象进行转换,比如从将外部微服务得到的对象转换为本域的业务对象 domainobject,将 domainobject 转为数据持久层的 dataobje ...

  6. 在 C++ 中与 QML 对象交互

    简述 所有的 QML 对象类型 - 无论由引擎内部实现还是由第三方源定义,都是 QObject 派生的类型.这意味着,QML 引擎可以使用 Qt 元对象系统动态实例化任何 QML 对象类型并检查创建的 ...

  7. android java style_Android 在Java代码中设置style属性--使用代码创建ProgressBar对象

    强烈推荐: 在andriod开发中,很大一部分都要与资源打交道,比如说:图片,布局文件,字符串,样式等等.这给我们想要开发一些公共的组件带来很大的困难,因为公共的组件可能更愿意以jar包的形式出现.但 ...

  8. php中newself(),在php代码中新建对象用到的new self与new static有什么不同

    我们在使用php代码新建对象的时候,一般会用到new self与new static,那么它们在使用的时候区别在哪里? 先说说new static(),new static与new self一样,在p ...

  9. 从不同步的代码块中调用了对象同步方法。_Java中Synchronized的用法

    Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行.拉勾IT课小编为大家分析. synchronized是Ja ...

最新文章

  1. suse linux ssh connerc failed
  2. xcode4 语法高亮和自动补全失效的解决办法
  3. Google新作:注意力机制是否真的能够提供模型的可解释性?
  4. Ⅵ:zookeeper的Watcher事件监听机制
  5. java 渐进式_JAVA转换jpg图片为渐进式图片
  6. 对象实例化指针_JVM第三课:一文讲透对象的内存布局和访问方式
  7. 《学习OpenCV3》第4章 图像和大型数组类型(持续更新)
  8. Python Revisited Day10 (进程与线程)
  9. 学安全测试需要多少钱?安全测试培训费一般多少?
  10. R语言 rgl plot3d函数
  11. 拯救者Y7000在ubuntu下的1660Ti驱动安装
  12. Flutter流畅性fps计算
  13. ps cs6调油画效果教程
  14. jenkins k8s 动态增减 jenkins-salve (2) 实现 slave 节点动态构建
  15. 2015校园O2O商业模式解析——从水果切入
  16. CFE的刷写与修改教程
  17. mysql 查询 及时间格式化
  18. 2013 11 24电脑操作
  19. 【C51】基于C51单片机的定时闹钟(含代码,电路,拿走即可用)
  20. 仓央嘉措经典语句分享

热门文章

  1. windows窗体(winform)中嵌入显示Excel工作表。
  2. hdu 5055(贪心)
  3. nyist -- 组队赛(二)
  4. JS权威指南笔记之数据类型
  5. centos出现磁盘坏道,怎么检索和修复
  6. Python学习-基础篇4 模块与包与常用模块
  7. 《第一行代码》学习笔记9-活动Activity(7)
  8. Restrict Users to Use Old Passwords
  9. ubuntu 安装intel iofrt 和icc编译器
  10. C++需要输出一个参数的地址时可能达不到预期的效果