连接类

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

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. python 安装模块 更新模块

    #显示模块pip list #显示过期模块pip list --outdated #安装模块pip install xxx #升级模块pip install --upgrade xxx

  2. SQLAlchmy模块详解

    之前写过一篇博客介绍过sqlalchemy的基本用法,本篇博客主要介绍除增删改查以外SQLAlchemy对数据库表的操作,主要内容有单表操作.一对多操作.多对多操作. 一.单表操作 单表操作的增删改查 ...

  3. NYOJ-58最少步数,广搜思想!

    最少步数 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 ->   Link  <- 这个题深搜广搜都是可以的,迷宫已经给出了,就看怎么做了:一般起点终点确定用广搜 ...

  4. [bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set

    寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相 ...

  5. [bzoj3238][Ahoi2013]差异_后缀数组_单调栈

    差异 bzoj-3238 Ahoi-2013 题目大意:求任意两个后缀之间的$LCP$的和. 注释:$1\le length \le 5\cdot 10^5$. 想法: 两个后缀之间的$LCP$和显然 ...

  6. P1340 兽径管理 洛谷

    https://www.luogu.org/problem/show?pid=1340 题目描述 约翰农场的牛群希望能够在 N 个(1<=N<=200) 草地之间任意移动.草地的编号由 1 ...

  7. CSS3(各UI元素状态伪类选择器受浏览器的支持情况)

    选择器 Firefox Safari Opera IE Chrome E:hover Y Y Y Y Y E:active Y Y Y N Y E:focus Y Y Y Y Y E:enabled ...

  8. Jsp标签字典开发_基于Spring+Hibernate

    目录 1. Jsp标签字典开发_基于Spring+Hibernate 1.1. 简述 1.2. 定义DictItem实体 1.3. 定义字典的@interface 1.4. 定义字典缓存类 1.5. ...

  9. Java 代理模式和装饰者模式的区别

    装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案:代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用: 装饰模式应该为所装饰的对象增强功能:代理模式对代理的 ...

  10. delphi的一些语法知识 以及参数传递问题,按引用方式传递参数,按值方式传递参数

    //delphi中exit,abort,break,continue 的区别 exit: 退出函数体abort: 遇到异常,安静处理,就是不显示不提示break: 退出当前循环体,包括for ,whi ...