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 ...
随机推荐
- 树莓派 - wiringPi
wiringPi其实和BCM2835 library类似,也是通过memmap, IOmap来实现在用户空间直接操作底层寄存器 wiringPi http://wiringpi.com/ Wiring ...
- odoo 权限配置讲解
今天来讲解一下odoo权限配置的简单讲解,配合公司开发的权限模块的使用,进行odoo权限配置的说明 BaseSecurityExtend 2.0模块 这是公司自主开发的一款针对odoo菜单级别进行可视 ...
- 洛谷 3871 [TJOI2010]中位数
[题解] 平衡树模板题,不过因为可以离线,所以有别的做法.把询问倒着做,变成删掉数字.求中位数,于是可以二分+树状数组. #include<cstdio> #include<cstr ...
- 洛谷 1850 NOIP2016提高组 换教室
[题解] 先用floyed处理出两点间的最短路. 设f[i][j][k]表示走到第i个教室,总共换了j次,当前换或者不换,期望的最小移动距离. 分情况讨论来转移即可. #include<cstd ...
- DFS求连通块(漫水填充法)
G - DFS(floodfill),推荐 Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I6 ...
- Pycharm下GitHub配置使用
1.下载并安装git 要连接GitHub,首先git是必不可少的,git的安装的基本使用很简单,这里略过.. 2.如图所示,进入Pycharm的Setting>>> Version ...
- 动态创建div(鼠标放上显示二维码)
最近的微信大行其道.各个网站上都给出的微信验证码,进行手机扫描加入. 怎么创建类似与点击鼠标弹出一个浮动的div显示二维码的这种效果. 1.首先制作好这样的图片,写css样式 <style ty ...
- SPOJ GSS6 Can you answer these queries VI
Can you answer these queries VI Time Limit: 2000ms Memory Limit: 262144KB This problem will be judge ...
- Jupyter notebook使用笔记
常用快捷键 For a Cell, Blue -> selecting. Green -> editing. Esc -> exist edit When the cell is ...
- HDU1755
这道题直接暴力枚举复杂度为 n!*m 但是k<100 , 所以我们可以通过取模用dp[i][j] 表示k=i 时,-x取模k为j的最小值 #include <cstdio> #inc ...