连接类

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

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. Win7解决无法在资源管理器中连接FTP问题

    需要连接FTP站点,但是又不想使用任何工具,使用电脑自带的资源管理器实现连接. 一般来说是能正常连接没有问题的,但是存在个别电脑不行. 试过好多办法不行,如下办法方法管用. 复制以下代码,本地保存为R ...

  2. win10下安装psql9,后无法访问数据库引擎

    1.修改安装文件兼容性,并启动安装 2.安装后 修改psql control center快捷方式的启动文件兼容性 3.修改 start workgroup engine 快捷方式的启动文件兼容性 一 ...

  3. spring+orm框架的兼容问题

    Springframework和Hibernate版本对应关系 org.springframework 3.0.x对应org.hibernate4.0.x版本 org.springframework ...

  4. Android BGABadgeView:BGABadgeLinearLayout以整体线性布局作为BadgeView(3)

     Android BGABadgeView:BGABadgeLinearLayout以整体线性布局作为BadgeView(3) Android BGABadgeView不仅可以把某个View作为B ...

  5. wangEditor

    wangEditor 基于javascript和css开发的 Web富文本编辑器, 轻量.简洁.易用.开源免费 http://www.wangeditor.com/index.html API htt ...

  6. Django组件:(6)cookie 和 session

    会话:会话可理解为客户端与服务器之间的一次会晤,在一次会晤中可能会包含多次请求和响应:在JavaWeb中,客户向某一服务器发出第一个请求开始,会话就开始了,直到客户关闭了浏览器会话结束. 在一个会话的 ...

  7. POJ3669 Meteor Shower

    http://poj.org/problem?id=3669 类似于迷宫的一道题 但是并没有 给出迷宫具体什么样 但是题目已说在坐标轴的第一象限 然后障碍就是 流星雨所砸范围 安全位置:永远不会发生危 ...

  8. UVA 140_Bandwidth

    题意: 定义一个结点的带宽是其距离所有相连结点的最远距离,一个图的带宽是图中所有结点带宽的最小值.给出一个图中各个结点的相邻情况,要求写出一个结点的排列,使得其所构成的图带宽最小. 分析: 枚举全排列 ...

  9. 记 SpringBoot1.* 转 Springoot2.0 遇到的问题

    1.拦截器问题 到2.0之后在配置文件中写 static-path-pattern: /static/** 已经不起作用(2.0需要在方法中配置) SpringBoot1.*写法 @Configura ...

  10. Java线程:Callable和Future

    接着上一篇继续并发包的学习,本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果.        Callable接口类似于Runnable,从名字就可以看出来了,但 ...