连接类

连接类有固定的使用模式,这是常用的乐观模式:

using (var conn = new SqlConnection(connstr))
{
conn.Open(); //执行各种数据库操作 }

悲观的、防御性的编程方式,这里在using语句结尾显示关闭了连接,并捕捉整个using语句的数据库异常:

try
{
using (var conn = new SqlConnection(connstr))
{
conn.Open(); //执行各种数据库操作 conn.Close();
}
}
catch (SqlException e)
{
throw;
}

事务

当使用多条语句修改数据库是,应将所有这些语句看作一个单元,要么完全成功修改数据库(提交),要么完全失败任何一条修改语句都不会被执行(回滚)。要想使用事务,先要引用System.Transactions装配体。事务的代码如下所示:

using (var scope = new TransactionScope())
{
using (var conn = new SqlConnection(connstr))
{
conn.Open();
// 执行各种数据库操作
} scope.Complete();
}

在这里,事务范围使用了默认构造函数,它意味着TransactionScopeOption.Required、IsolationLevel.Serializable、TimeOut=1分钟。

事务通过使用scope.Complete显式标记为完成。缺少这个调用,事务将被回滚。

事务范围内可以有多个连接,都被看作一个整体。

事务的隔离级别:

ReadCommitted 读取已经提交的数据
ReadUncommitted 读取还没有提交的数据
RepeatableRead  
Serializable  

命令

打开数据库连接之后,需要定义要执行的命令。对Sql Server可用的命令类型有两种:文本、和存储过程。

定义文本类型命令的方法如下。因为文本类型的命令是默认值,所以不需要显式指定命令类型:

var sql = "SELECT ContactName FROM Customers";
var cmd = new SqlCommand(sql, conn);

定义存储过程类型的命令:

var cmd = new SqlCommand("CustOrderHist", conn) { CommandType = CommandType.StoredProcedure };
cmd.Parameters.AddWithValue("@CustomerID", "QUICK");

执行命令

定义了命令之后,需要执行它。根据返回结果不同分成三种执行方法。

ExecuteNonQuery方法一般用于UPDATE,INSERT,或DELETE语句。它执行命令,并返回受影响的行数。

打开连接后,添加如下代码:

var cmd = new SqlCommand("CustOrderHist", conn)
{
CommandType = CommandType.StoredProcedure
};
cmd.Parameters.AddWithValue("@CustomerID", "QUICK");
var rows = cmd.ExecuteNonQuery();

ExecuteReader方法执行命令,并返回一个数据阅读器对象。在打开连接语句之后,添加如下代码:

var sql = "SELECT ContactName,CompanyName FROM Customers";
var cmd = new SqlCommand(sql, conn);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("Contact: {0,-20} Company: {1}",
reader[0], reader[1]);
}

ExecuteScalar执行返回一个标量值的命令。在打开连接语句之后,添加如下代码:

var sql = "SELECT COUNT(*) FROM Customers";
var cmd = new SqlCommand(sql, conn);
var custs = (int)cmd.ExecuteScalar();
Console.WriteLine(custs);

ExecuteScalar方法返回一个object对象,需要将其转化为实际的类型。

调用存储过程

调用不返回值的存储过程

这里列出两个例子,使用了Northwind数据库的Region表。

更新记录

存储过程定义如下:

CREATE PROCEDURE RegionUpdate (@RegionID INTEGER,
@RegionDescription NCHAR(50)) AS
SET NOCOUNT OFF
UPDATE Region
SET RegionDescription = @RegionDescription
WHERE RegionID = @RegionID
GO

如前所述,定义一个命令,并添加他的参数和参数值:

var cmd = new SqlCommand("RegionUpdate", conn) { CommandType = CommandType.StoredProcedure };

cmd.Parameters.AddWithValue("@RegionID", 23);
cmd.Parameters.AddWithValue("@RegionDescription", "Something"); cmd.ExecuteNonQuery();

删除记录

存储过程定义如下:

CREATE PROCEDURE RegionDelete (@RegionID INTEGER) AS
SET NOCOUNT OFF
DELETE FROM Region
WHERE RegionID = @RegionID
GO

在命令定义部分,使用SqlParameter构造函数来构造命令参数:

var cmd = new SqlCommand("RegionDelete", conn) { CommandType = CommandType.StoredProcedure };

cmd.Parameters.Add(new SqlParameter("@RegionID", SqlDbType.Int, 0, "RegionID"));
cmd.UpdatedRowSource = UpdateRowSource.None;

构造完命令并添加参数定义之后,通过参数名字检索出参数并设置它的值,然后执行命令:

cmd.Parameters["@RegionID"].Value = 999;
cmd.ExecuteNonQuery();

也可以通过参数位置检索参数。

调用返回输出参数的存储过程

下面的例子演示插入一个记录到数据库并且返回该记录的主键给调用者。

CREATE PROCEDURE RegionInsert(@RegionDescription NCHAR(50),
@RegionID INTEGER OUTPUT)AS
SET NOCOUNT OFF
SELECT @RegionID = MAX(RegionID)+ 1
FROM Region
INSERT INTO Region(RegionID, RegionDescription)
VALUES(@RegionID, @RegionDescription)
GO

插入过程创造一个新的Region记录。因为主键由数据库自己生成,这值被作为一个输出参数从过程(@RegionID)返回。下面代码显示我们将如何调用RegionInsert存储过程:

var cmd = new SqlCommand("RegionInsert", conn) { CommandType = CommandType.StoredProcedure };
cmd.Parameters.Add(new SqlParameter("@RegionDescription",
SqlDbType.NChar,
50,
"RegionDescription")); cmd.Parameters.Add(new SqlParameter("@RegionID",
SqlDbType.Int,
0,
ParameterDirection.Output,
false,
0,
0,
"RegionID",
DataRowVersion.Default,
null)); cmd.UpdatedRowSource = UpdateRowSource.OutputParameters;

第二参数,@RegionID,包括它的参数方向,在这个例子中是Output。代码的最后一行UpdateRowSource枚举被用来指明数据将从这个存储过程通过输出参数返回。

调用这个存储过程类似于前面的例子,除了输出参数是在执行过程之后被读取:

cmd.Parameters["@RegionDescription"].Value = "South West";
cmd.ExecuteNonQuery();
var newRegionID = (int)cmd.Parameters["@RegionID"].Value;

数据读取器

不能直接实例化一个数据读取器,只能由相应的命令对象通过ExecuteReader方法返回。

using (var conn = new SqlConnection(connstr))
{
conn.Open(); var sql = "SELECT ContactName,CompanyName FROM Customers";
var cmd = new SqlCommand(sql, conn); var reader = cmd.ExecuteReader();
while (reader.Read())
{
var contact = reader.GetString(0);
var company = reader.GetString(1); Console.WriteLine("'{0}' from {1}", contact, company);
} reader.Close(); conn.Close();
}

可以通过位置或者名称读取字段值,然后将返回的object值强制转换为合适的数据类型:

var contact = (string)reader[0];
var company = (string)reader["CompanyName"];

Ado.net设计模式的更多相关文章

  1. Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)

    jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...

  2. ADO.NET Entity Framework 在哪些场景下使用?

    在知乎回答了下,顺手转回来. Enity Framework已经是.NET下最主要的ORM了.而ORM从一个Mapping的概念开始,到现在已经得到了一定的升华,特别是EF等对ORM框架面向对象能力的 ...

  3. 设计模式(七)适配器模式(Adapter Pattern)

    一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将“将现存的对象”在新的环境中进行调用 ...

  4. Entity Framework与ADO.Net及NHibernate的比较

    Entity Framework  是微软推荐出.NET平台ORM开发组件, EF相对于ado.net 的优点 (1)开发效率高,Entity Framework的优势就是拥有更好的LINQ提供程序. ...

  5. C#设计模式(7)——适配器模式(Adapter Pattern)

    一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将“将现存的对象”在新的环境中进行调用 ...

  6. 关于ADO.NET的基本介绍

    关于ADO.NET ADO.NET是微软提供的一种数据库访问方式.他使得.NET程序员对于不同的数据库都能采用相同的访问方式. Connection 连接 Connection是一个数据库连接类,他负 ...

  7. .NET设计模式(8):适配器模式(Adapter Pattern)

    ):适配器模式(Adapter Pattern)    适配器模式(Adapter Pattern) --.NET设计模式系列之八 Terrylee,2006年2月 概述 在软件系统中,由于应用环境的 ...

  8. 浅谈数据库技术,磁盘冗余阵列,IP分配,ECC内存,ADO,DAO,JDBC

    整理-----数据库技术,磁盘冗余阵列,IP分配, ECC内存,ADO, DAO,JDBC 1.MySQL MySQL是最受欢迎的开源SQL数据库管理系统,它由 MySQL AB开发.发布和支持.My ...

  9. [.net 面向对象程序设计深入](26)实战设计模式——使用Ioc模式(控制反转或依赖注入)实现松散耦合设计(1)

    [.net 面向对象程序设计深入](26)实战设计模式——使用IoC模式(控制反转或依赖注入)实现松散耦合设计(1) 1,关于IOC模式 先看一些名词含义: IOC: Inversion of con ...

随机推荐

  1. ruby rspec安装

    在rubymine里新建Rails application

  2. The Text Splitting (将字符串分成若干份,每份长度为p或q)

    Description You are given the string s of length n and the numbers p, q. Split the string s to piece ...

  3. The Bells are Ringing(枚举)

    Description Perhaps you all have heard the mythical story about Tower of Hanoi (The details of this ...

  4. python 中文转码 Excel读csv

    大家都知道Excel读csv用的是ascii编码,我认为,ascii没有中文,所以这里指的应该是utf-8. 我遇到的问题是这样的,unity项目只能用txt文件,有一堆数据表用txt的文档保存下来了 ...

  5. hdu 5029树链剖分

    /* 解:标记区间端点,按深度标记上+下-. 然后用线段树维护求出最小的,再将它映射回来 */ #pragma comment(linker, "/STACK:102400000,10240 ...

  6. [ C语言 ] 迷宫 迷宫生成器 [ 递归与搜索 ]

    [原创]转载请注明出处 [浙江大学 程序设计专题] [地图求解器] 本题目要求输入一个迷宫地图,输出从起点到终点的路线. 基本思路是从起点(Sx,Sy)每次枚举该格子上下左右四个方向,直到走到终点(T ...

  7. 【ZJOI2017 Round1练习】D8T1 mushroom(点分治)

    题意: 思路: num[a[u]]表示存在a[u]这个颜色且终点在u子树中的链长总和 ans[i]表示以当前的u为根,前面的子树对i的贡献之和 ..]of longint; size,f,ans,su ...

  8. mysql控制流程函数(case,if,ifnull,nullif)

    1.case...when... 用法 参考:http://www.cnblogs.com/qlqwjy/p/7476533.html CASE value WHEN [compare-value] ...

  9. msp430入门编程05

    msp430中C语言的运算符和表达式 msp430中C语言的程序结构06 msp430中C语言的函数及实现07 msp430中C语言操作端口I/O10 msp430中C语言的模块化头文件及实现11 m ...

  10. iLBC 压缩比

    *---------------------------------------------------* *                                             ...