ADO.NET之一:连接层
ADO.NET大部分由System.Data.dll核心程序集来表示。
ADO.NET类库有三种完全不听的方式来实现数据访问:连接式、断开式和通过Entity框架。连接式就是会一直占用网络资源,断开式获取数据就可以断开连接,Entity其实是一种数据访问的API,到时候我们在详细介绍。
本篇主要介绍连接式访问数据库。
一些核心对象
对象 基类 实现接口 作用
Connection DbConnection IDbConnection 连接和断开数据源,提供了相关事务对象的访问
Command DbCommand IDbCommand 代表SQL查询语句或者存储过程名,同意提供了相关数据读取器对象的访问
DataReader DbDataReader IDataReader和IDataRecord 提供只读只向前形式的数据访问
DataAdapter DbDataAdapter IDataAdapter和IDbDataAdapter 在数据库和调用者之前传递DataSet,内置4个命名对象来实现数据的查询、插入、修改和删除
Parameter DbParameter IDataParameter和IDbDataParameter 在参数化查询中表示参数
Transaction DbTransaction IDbTransaction 实现数据库事务
基类都定义在 System.Data.Common 命名空间中,接口定义在 System.Data命名空间。
尽管这些类的命名对于不用的数据提供程序不尽相同(比如SqlConnection,OracleConnection,OdbcConnection,MySqlConnection),但是它们都是从相同的基类(DbConnection)继承并且实现相同的接口(IDbConnection),你掌握其中一种,其他的也差不多。
System.Data命名空间的类型
System.Data命名空间的核心成员
这个命名空间绝大数类都在进行ADO.NET断开连接层编程时使用,下一章细说。
关于接口里面的属性,方法等详细,先写出接口然后转定义去查看,因为太多了这里就不说了。
使用接口的抽象数据提供程序
enum DataProvider //声明的枚举,代表使用什么数据库
{
SqlServer,OleDb,Odbc,None
}
static void Main(string[] args)
{
Console.WriteLine("请开始你的表演:"); IDbConnection myCn = GetConnection(DataProvider.SqlServer);
Console.WriteLine("你链接的是:{0}",myCn.GetType().Name);
//打开、使用,关闭
Console.ReadLine();
}
static IDbConnection GetConnection(DataProvider dp)
{
IDbConnection conn = null;
switch (dp)
{
case DataProvider.SqlServer:
conn = new SqlConnection();
break;
case DataProvider.OleDb:
conn = new System.Data.OleDb.OleDbConnection();
break;
case DataProvider.Odbc:
conn = new System.Data.Odbc.OdbcConnection();
break;
case DataProvider.None:
break;
default:
break;
}
return conn;
}
使用应用程序配置文件添加灵活性
我们可以把值存储在*.config里面,如果需要改动只要该配置里面的内容就可以了。
Console.WriteLine("请开始你的表演:"); string dataProvString = ConfigurationManager.AppSettings["provider"];
//把字符串转成枚举
DataProvider dp = DataProvider.None;
if (Enum.IsDefined(typeof(DataProvider), dataProvString))
{
dp = (DataProvider)Enum.Parse(typeof(DataProvider), dataProvString);
}
else
{
Console.WriteLine("该值不存在");
}
IDbConnection myCn = GetConnection(dp);
if (myCn!=null)
Console.WriteLine("你链接的是:{0}", myCn.GetType().Name);
//打开、使用,关闭
Console.ReadLine();
工厂模型
System.Data.Common命名空间下有一个叫做DbProviderFactories的类帮助我们从 DbProviderFactory继承的类获取数据提供程序。使用静态方法GetFactory(),并指定包含提供程序功能的.NET命名控件的名称,能够获得代表该数据提供城西DbProviderFactory对象。
例如:
来看一个工厂获取数据的完整列子
Console.WriteLine("请开始你的表演:");
string dp = ConfigurationManager.AppSettings["provider"];
string cnStr = ConfigurationManager.AppSettings["cnStr"]; //得到工程提供程序
DbProviderFactory df = DbProviderFactories.GetFactory(dp); //得到连接对象
using (DbConnection cn=df.CreateConnection())
{
//通过反射服务得到全名
Console.WriteLine("链接实例为:{0}",cn.GetType().Name);
cn.ConnectionString = cnStr; //设置连接字符串
cn.Open(); //打开数据库 //得到命名对象
DbCommand cmd = df.CreateCommand();
Console.WriteLine("命名的实例名称为:{0}",cmd.GetType().Name);
cmd.Connection = cn;//操作数据
cmd.CommandText = "select * from News"; //得到数据读取器对象
using (DbDataReader dr=cmd.ExecuteReader())
{
Console.WriteLine("数据读取器实例为:{0}",dr.GetType().Name); while (dr.Read())
{
Console.WriteLine("新闻的标题为:{0}",dr["Title"].ToString());
}
}
}
Console.ReadLine();
工厂的潜在缺陷
优点:最灵活的方式构建数据访问库。
缺点:正是因为使用都是抽象类,也就是基类,当我们想访问某个具体类的特殊成员就需要转型。会使代码不易维护。
<connectionStrings>元素
上面写的<appSettings>元素是用来保存一些稳定的并且不想给用户看到的数据。类似于键/值。而<connectionStrings>元素才是用来连接数据库的。
配置:
使用:
进入主题:
ADO.NET连接层
一般的步骤:
①创建、配置、打开连接对象
②创建、配置一个命名对象,通过构造参数或Connection属性指定连接对象
③执行配置后的命令对象的ExecuteReader()方法
④使用数据读取器的Read()方法一条一条处理记录
例如:
string strConn = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;
using (SqlConnection cn=new SqlConnection())//建立并打开一个连接
{
cn.ConnectionString = strConn;
cn.Open();
string strSQL = "select * from News";
//建立一个SQL命令对象
SqlCommand myCommand = new SqlCommand(strSQL,cn);
using (SqlDataReader myDataReader=myCommand.ExecuteReader())
{
while (myDataReader.Read())
{
Console.WriteLine("Title:{0}\r\nContent:{1}", myDataReader["Title"], myDataReader["Contents"]);
}
}
} Console.ReadLine();
先来看看基类DbConnection,一下就是一些属性和方法,属性基本都是只读的,不好修改。
使用ConnectionStringBuilder对象
这是使用以编程方式使用连接字符串,通过它能使用强类型化的属性来指定名称/值对。
下面就避免了手写连接字符串了,还可以适当的修改一些属性。
SqlConnectionStringBuilder cnStrBuilder = new SqlConnectionStringBuilder();
cnStrBuilder.InitialCatalog = "NewsDB";
cnStrBuilder.DataSource = @"SEALEE\SEALEE";
cnStrBuilder.ConnectTimeout = ;
cnStrBuilder.IntegratedSecurity = false;
cnStrBuilder.Password = "";
cnStrBuilder.UserID = "sa";
using (SqlConnection cn=new SqlConnection())
{
cn.ConnectionString = cnStrBuilder.ConnectionString;
cn.Open();
ShowStatus(cn);
}
使用命令对象
SqlCommand类型时SQL查询、表名和存储过程的一种面向对象的表示方法。可以使用CommandType属性来指定命令类型。
DbCommand类型的成员
如:增、删、改
使用数据读取器
数据读取器是只向前的数据流,并且一次返回一条记录,只有使用Select语句才会有用,会一直保持打开连接状态。
可以快速获取大批数据并且不会保存在内存中。
几种用法:
或则
获取多个结果集
我们执行语句就查询多张表。用DataSet.Table[1]就是第二张表。
连接,添加,删除,更新数据
连接逻辑
private SqlConnection sqlcn = null;
public void OpenConnection(string connectionString)
{
sqlcn = new SqlConnection();
sqlcn.ConnectionString = connectionString;
sqlcn.Open();
}
public void CloseConnection()
{
sqlcn.Close();
}
增加插入逻辑
//还可以写个强类型作为参数传进去
public void InsertAuto(int id,string title,string contents,DateTime dt)
{
string sql = string.Format("insert into News(CateID,Title,Contents,CreateDate) values({0},{1},{2},{3})",id,title,contents,dt);
using (SqlCommand cmd =new SqlCommand(sql,this.sqlcn))
{
cmd.ExecuteNonQuery();
}
}
删除逻辑
public void DeleteNews(int id)
{
string sql = string.Format("Delete from News where id={0}",id);
using (SqlCommand cmd=new SqlCommand(sql,sqlcn))
{
cmd.ExecuteNonQuery();
}
}
更新
public void Update(int id,int id1)
{
string sql = string.Format("update News set CateID={0} where id={1}",id,id1);
using (SqlCommand cmd=new SqlCommand(sql,sqlcn))
{
cmd.ExecuteNonQuery();
}
}
返回集合
public List<News> GetList()
{
List<News> inv = new List<News>();
string sql = "select * from News";
using (SqlCommand cmd=new SqlCommand(sql,this.sqlcn))
{
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
inv.Add(new News()
{
CateID = int.Parse(dr["CateID"].ToString())
});
}
dr.Close();
} return inv;
}
返回DataTable
public DataTable GetTable()
{
DataTable inv = new DataTable();
string sql = "select * from News";
using (SqlCommand cmd=new SqlCommand(sql,this.sqlcn))
{
SqlDataReader dr = cmd.ExecuteReader();
inv.Load(dr);
dr.Close();
} return inv;
}
使用参数化命令
ADO.NET命令对象使用一个集合来保存参数对象。这个集合默认是空的,可以添加任意多的参数对象并映射到SQL语句中的占位符参数。如何需要把SQL查询中的参数和命令对象参数集合中国某一个成员关联的话,只需要在SQL文本参数前面加@符号
//还可以写个强类型作为参数传进去
public void InsertAuto(int id, string title, string contents, DateTime dt)
{
//使用@符号
string sql = string.Format("insert into News(CateID,Title,Contents,CreateDate) values(@CateID,@Title,@Contents,@CreateDate)");
using (SqlCommand cmd = new SqlCommand(sql, this.sqlcn))
{
//填充参数集合
SqlParameter param = new SqlParameter();
param.ParameterName = "@CateID";
param.Value = id;
param.SqlDbType = SqlDbType.Int; //这里的类型最好跟数据库里面的类型对应
cmd.Parameters.Add(param); param = new SqlParameter();
param.ParameterName = "@Title";
param.Value = title;
param.SqlDbType = SqlDbType.VarChar;
cmd.Parameters.Add(param);
//..... 更多参数继续
cmd.ExecuteNonQuery();
}
}
运行存储过程
存储过程是存储在数据库内的一段已命名的SQL语句代码,你可以构造存储过程,返回一组行或标量数据类型,或进行其他头意义的处理(如插入,更新,删除),也可以接受一些可选参数。
使用方法:
using (SqlCommand cmd = new SqlCommand("GetNews", this.sqlcn))
{
cmd.CommandType = CommandType.StoredProcedure;//这句话一定得有 //填充参数集合
SqlParameter param = new SqlParameter();
param.ParameterName = "@id";
param.Value = id;
param.SqlDbType = SqlDbType.Int; //这里的类型最好跟数据库里面的类型对应
param.Direction = ParameterDirection.Input;
cmd.Parameters.Add(param);
param = new SqlParameter();
param.ParameterName = "@Title"; param.SqlDbType = SqlDbType.VarChar;
param.Direction = ParameterDirection.Output;//输出参数
cmd.Parameters.Add(param);
//..... cmd.ExecuteNonQuery();
string a = (string)cmd.Parameters["@Title"].Value; //返回输出参数
}
数据库事务
事务是一组数据库操作,作为一个整体,要么全部完成要么全部失败。
SqlTransaction类型定义了一个Save()的成员,它允许我们定义保存点,这个概念允许我们把失败的事务回滚到一个保存点,而不是回滚整个事务。使用Rollback()可以把保存点的名字作为参数传递进去,这样就不是整个回滚了。
using (SqlConnection con=new SqlConnection(strConn))
{
con.Open();
string sql = string.Format("delete from News where NewsID={0}", ); using (SqlCommand cmd = new SqlCommand(sql, con))
{
SqlTransaction tx = null;
try
{
tx = con.BeginTransaction();
cmd.Transaction = tx;
cmd.ExecuteNonQuery();
if (false) //模拟错误
{
throw new Exception("错了哦");
}
tx.Commit();//提交
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
tx.Rollback();//执行回滚
}
}
}
ADO.NET之一:连接层的更多相关文章
- 简述ADO.NET的连接层
前面曾提到过ADO.NET的连接层允许通过数据提供程序的连接.命令.数据读取器对象与数据库进行交互.当想连接数据库并且使用一个数据读取器对象来读取数据时.需要实现下面的几个步骤 * 创建.配置.打开连 ...
- ADO.NET 之断开连接层
定义: 使用ADO.NET断开连接层,就会使用System.Data命名空间的许多成员(主要是DataTable.DataTable.DataRow.DataColumn.DataView和DataR ...
- ASP.NET SignalR2持久连接层解析
越是到年底越是感觉浑身无力,看着啥也不想动,只期盼着年终奖的到来以此来给自己打一针强心剂.估摸着大多数人都跟我一样犯着这样浑身无力的病,感觉今年算是没挣到啥钱,但是话也不能这么说,搞得好像去年挣到钱了 ...
- caffe之(四)全连接层
在caffe中,网络的结构由prototxt文件中给出,由一些列的Layer(层)组成,常用的层如:数据加载层.卷积操作层.pooling层.非线性变换层.内积运算层.归一化层.损失计算层等:本篇主要 ...
- MySQL的三层架构之一----连接层
1.mysql的服务端可以分为三层,分别是连接层,SQL层,存储层. 2.架构图 3.连接层定义了通信server端与client协议:
- asp.net学习之ado.net(连接模式访问)
原文:asp.net学习之ado.net(连接模式访问) ado.net框架支持两种模式的数据访问: 连接模式(Connected)和非连接模式(disconnected).这一节介绍如何使用连 ...
- resnet18全连接层改成卷积层
想要尝试一下将resnet18最后一层的全连接层改成卷积层看会不会对网络效果和网络大小有什么影响 1.首先先对train.py中的更改是: train.py代码可见:pytorch实现性别检测 # m ...
- tensorflow 1.0 学习:池化层(pooling)和全连接层(dense)
池化层定义在 tensorflow/python/layers/pooling.py. 有最大值池化和均值池化. 1.tf.layers.max_pooling2d max_pooling2d( in ...
- mnist全连接层网络权值可视化
一.数据准备 网络结构:lenet_lr.prototxt 训练好的模型:lenet_lr_iter_10000.caffemodel 下载地址:链接:https://pan.baidu.com/s/ ...
随机推荐
- python3与python2的区别 记录一波
1.性能 Py3.0运行 pystone benchmark的速度比Py2.5慢30%.Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可 以取得很好的优化结果. Py3.1性能比Py2 ...
- inventor卸载不干净
AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...
- Unity 去除场景中的雾效果
Windows——Lighting——Setting,然后出现下面窗口,把Other Setting下,Fog的对勾去掉就可以了.
- android shape.xml 属性详解
转载源:http://blog.csdn.net/harvic880925/article/details/41850723 一.简单使用 刚开始,就先不讲一堆标签的意义及用法,先简单看看shape标 ...
- app启动黑屏
由于在手机上多次删除应用,导致加载app时加载缓存图片缺失,进行如下操作: 删除Xcode DerivedData目录释放空间: 1.首先切换到 Finder 程序,打开“前往”菜单. 2.然后按住 ...
- springboot2.x如何配置全局自定义异常
为什么要捕获异常? 我们开发中,经常运行时,代码会报错,这时候我们有可能抛出异常,而不是用try..catch来解决.而且现在前后端分离,如果不捕获异常的话,前端那边的人估计会被报的错搞得焦头烂额的. ...
- Spring Data JPA 事务
Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套 JPA 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作.它提供了包括增删改查等在内的常 ...
- (生产)jsonp - 跨域请求
参考:https://github.com/webmodules/jsonp 参数: url (String) url to fetch opts (Object), optional param ( ...
- [原创] Debian9上配置Samba
Samba概述 Samba是一套使用SMB(Server Message Block)协议的应用程序,通过支持这个协议,Samba允许Linux服务器与Windows系统之间进行通信,使跨平台的互访成 ...
- 搭建日志环境并配置显示DDL语句
现在一般用log4j用的比较多,用slf4j用的比较少,所有这里我们就不用 hibernate内置的slf4j了. 用到slf的接口,log4j的实现. 要在hibernate中使用log4j,如图所 ...