Ado.net设计模式
连接类
连接类有固定的使用模式,这是常用的乐观模式:
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设计模式的更多相关文章
- Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)
jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...
- ADO.NET Entity Framework 在哪些场景下使用?
在知乎回答了下,顺手转回来. Enity Framework已经是.NET下最主要的ORM了.而ORM从一个Mapping的概念开始,到现在已经得到了一定的升华,特别是EF等对ORM框架面向对象能力的 ...
- 设计模式(七)适配器模式(Adapter Pattern)
一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将“将现存的对象”在新的环境中进行调用 ...
- Entity Framework与ADO.Net及NHibernate的比较
Entity Framework 是微软推荐出.NET平台ORM开发组件, EF相对于ado.net 的优点 (1)开发效率高,Entity Framework的优势就是拥有更好的LINQ提供程序. ...
- C#设计模式(7)——适配器模式(Adapter Pattern)
一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将“将现存的对象”在新的环境中进行调用 ...
- 关于ADO.NET的基本介绍
关于ADO.NET ADO.NET是微软提供的一种数据库访问方式.他使得.NET程序员对于不同的数据库都能采用相同的访问方式. Connection 连接 Connection是一个数据库连接类,他负 ...
- .NET设计模式(8):适配器模式(Adapter Pattern)
):适配器模式(Adapter Pattern) 适配器模式(Adapter Pattern) --.NET设计模式系列之八 Terrylee,2006年2月 概述 在软件系统中,由于应用环境的 ...
- 浅谈数据库技术,磁盘冗余阵列,IP分配,ECC内存,ADO,DAO,JDBC
整理-----数据库技术,磁盘冗余阵列,IP分配, ECC内存,ADO, DAO,JDBC 1.MySQL MySQL是最受欢迎的开源SQL数据库管理系统,它由 MySQL AB开发.发布和支持.My ...
- [.net 面向对象程序设计深入](26)实战设计模式——使用Ioc模式(控制反转或依赖注入)实现松散耦合设计(1)
[.net 面向对象程序设计深入](26)实战设计模式——使用IoC模式(控制反转或依赖注入)实现松散耦合设计(1) 1,关于IOC模式 先看一些名词含义: IOC: Inversion of con ...
随机推荐
- 全国高校json数据包(复python解析代码)
由于这段时间需要有关学校的三级联动插件,找了很久没有找到合适的,所以去教育部官网下载了一份全国普通高校名单(2019年), 这里附上解析该xls文件的代码 import xlrd import jso ...
- JS 去除字符串空格
$.trim()是jQuery提供的函数,用于去掉字符串首尾的空白字符. "abc 123 def".replace(/\s/g, "") 去除所有的空格
- NRF24L01注意点
nrf24L01被设置为接收模式后,可通过6个不同的数据通道(data pipe)接收数据. 每个数据通道都有一个唯一的地址但是各数据通道的频率是相同的.这意味着可以有6个被配置成发送状态的nRF24 ...
- RS232
RS232的最大的传输速率大约10KBytes/s. 全双工工作方式,异步.数据是8位作为一块来发送的,先发送最低位,最后发送最高位. 在232通信中: Both side of the cable ...
- [OJ#40]后宫佳丽
[OJ#40]后宫佳丽 试题描述 如果机房要关门了,或者有妹子在等你,你可以直接看最后一句话. Fyq 是一只饥渴的鸭子. Fyq 有一个充实的后宫,可惜他总是体力不支,为此他经常苦恼,总是想方设法让 ...
- 使用vim正则表达式删除C/C++注释 及 两种注释风格替换
/*对于C风格的注释可以使用如下命令*/ :%s/\_s*\/\*\(\S\|\_s\)\{-}\*\///g //对于C++风格注释 :%s/\/\/.*//g /*...*/ -> //.. ...
- Java操作redis【二十】
1.首先需要将redis的绑定地址为127.0.0.1去掉,同时将redis的保护模式去掉,并且开放6379端口. 如果是保护模式需要输入密码才能连接. (1)去掉绑定地址: (2)去掉保护模式: ( ...
- 类(Class)
类 · 目的 面向对象的最主要目的是提高程序的重复使用性. · 包括 属性(attribute).方法(method) · 示例 class Bird(object): have_feather = ...
- [bzoj3306]树_dfs序_线段树_倍增lca
树 bzoj-3306 题目大意:给定一颗n个节点的树,支持换根.修改点权.查询子树最小值. 注释:$1\le n,q\le 10^5$. 想法: 如果没有换根操作,就是$dfs$序+线段树维护区间最 ...
- [bzoj4300]绝世好题_二进制拆分
绝世好题 bzoj-4300 题目大意:题目链接. 注释:略. 想法: 二进制拆分然后用一个数组单独存一下当前答案即可. Code: #include <iostream> #includ ...