自已接触过的数据访问方式总结
程序=代码+数据。数据这里主要说关于数据库的操作。
基本的SQL是高度非过程化的语言,简单理解,就是没有流程控制,像条件判断和循环。满足不了开发需要。
所以为了实现查询的流程控制。有以下几种方法。
嵌入式SQL语句,简单说就是把SQL嵌入到高级语言里,SQL语句还是直接执行,由高级语言来实现流程控制。
比如if(**){exec sql **},这方面基本全忘光了,貌似学PB的时候用过,这种技术比较底层,很古老,高级开发很少用到。
PL/SQL和存储过程,存储过程实质就是一个特殊的PL/SQL块,可以永久的保存在数据库中以供其他程序调用。
PL/SQL是对基本SQL语句的扩展,增加了过程化语句的功能,由SQL语句自已实现流程控制。
书上的原话:
PL/SQL块主要有两种类型,即命名块和匿名块。匿名块每次使用时都要进行编译,除此之外,该类块不在数据库中存储并且不能直接从其他的PL/SQL块中调用。过程、函数、包和触发器都属于命名块,这类构造没有匿名块的限制,它们可以存储数据库中并在适当的时候运行。
我个人只接触过存储过程和触发器。
简单的存储过程示例
ALTER PROCEDURE [dbo].[firelateinvitation] -- Add the parameters for the stored procedure here @num int, @type int AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; if @type=1 begin select top (@num) * from TB_Forum_Invitation,TB_Forum_Plate where TB_Forum_Invitation.Invitation_Plateid=TB_Forum_Plate.Plate_Id order by Invitation_Ftime desc end else if @type=2 begin select top (@num) * from TB_Forum_Invitation,TB_Forum_Plate where TB_Forum_Invitation.Invitation_Plateid=TB_Forum_Plate.Plate_Id order by Invitation_Ranking desc end END
if就是过程化语句的流程控制的一种。
PS:存储过程不止能反回查询结果,还可以有其他单独的返回值,由参数决定
IN类型的参数 OUT类型的参数 IN-OUT类型的参数
值被 传递给子程序 返回给调用环境 传递给子程序且,返回给调用环境
默认为IN型。
简单的触发器示例
ALTER trigger [dbo].[lastbacktime] ON [dbo].[TB_Forum_Invitation] AFTER INSERT AS BEGIN update database_Forum.dbo.TB_Forum_Invitation set Invitation_LastBackTime=getdate() where Invitation_Id=(select Invitation_Id from inserted) END
……工作需求并未要求写太复杂的触发器,有印象的是为了实现级联删除和修改,也不提倡写大量的复杂的触发器,不利于维护。
实际上,会写SQL查询的只要再多一点的付出就能写出同样功能的存储过程,我工作中其实用的不多。
存储过程优点主要是省流量高效:传一大串SQL语句,到数据库里编译再执行。传几个参数调用已经编译好的方法,性能哪个高很明显。至于分布式,工作还没接触到。
ODBC,JDBC等各种数据库的区别,只是业余看过几篇文章,说实在的,不是很清楚。
在这里写的也都是开发里用过的技术。
ODBC,PB课程设计用过,要建立ODBC数据源,程序才可以访问,Access和PowerDesign也用到过。
JDBC,JAVA练习时用过。
OleDb,操用EXCEL时,使用ACCESS数据库里用过。
ADO.NET是封装的ODBC,用的最多程序使用ADO.NET,ADO.NET通过ODBC实现功能,这里也主要说ADO.NET。
第一份net 工作开发主要用的就是ADO.NET。
数据库操作方法。
最基本的ADO.NET。
主要对象
connection,连接,最主要用的sqlconnection
command SqlCommand,CommandType 类型,可以指定是SQL语句Text,还是存储过程StoredProcedure,text查询语句(type为语句),存储过程名(type为存储过程)。
sqlparameter,参数,防止注入。
查询方法,ExecuteNonQuery,返回影向的行数
SqlTransaction cmd.Connection = conn;
// SqlTransaction tx = conn.BeginTransaction();
// cmd.Transaction = tx;
事务操作。
sqlparameter,参数,防止SQL注入。
查询方法,ExecuteNonQuery,返回影向的行数
ExecuteReader 游标,返回一条再下一条,要保持数据库的连接,嵌入式SQL,ODBC都有游标的概念。
ExecuteScalar 有则返回第一条,无则返回NULL
SqlDataAdapter 适配器
da.Fill(ds, "ds"); 适配器的原理是,调用sqlcommand的ExecuteReader方法,把每一条数据放入dataSet中的某改表中的一行。迭代。
迭代完成后就断开与数据库的连接,反回dataset与DataReader相比省数据库的资源,但占内存。
dataset 可以存多个datatable。
dataset datatable 很多老的项目,和写的自定义控件,都主要用的datatable,datarow作为操作对象。
JAVA里似乎没有与SqlDataAdapter 和dataset对应的对象 但可以自已实现(一般开发都会有写的工具类,实现了类似dataset的对象)。
DataAdapter 不止有用游标迭代填充到DataSet中的方法。
更高级的应用是,修改DataSet,然后再更新回数据库,等于是程序代写了SQL,这个功能,由另一个对象SqlCommandBuilder实现。再调用DataAdapter对象的Update方法。
常用的代码生成器的DAL层就是由ADO.NET实现。目前的不少公司还用这种方式开发,生成基本的,有其他需求,再自已拼SQL,而调用ADO.NET的过程多被封装在相应的SQLhelper工具类里。
缺点是:有时候拼些简单但繁琐的SQL很烦人。手拼SQL,容易拼错,没准就是哪块拼错了,浪费很多调试时间。
我一开始写SQL的时候经常总忘写‘’,有时多写个where,有时拼。推荐在数据库写好语句拼好粘到程序里,我倒是经常直接在程序里拼……
更大的缺点的是不利于重用,不利于修改和扩充,不灵活。谁写的SQL,谁最清楚,但过段时间,可能也得想一会, 就更别说其他人了,而且,很多人写DLL层的SQL还不加注释。就算有注释,有时如果有需求,还得在之前的SQL语句里找修改的位置。
这是得到数据到DataSet的部分,而在取DataSet的数据时,多数是按DataRow列的名称或编号取,就算是复制也觉得麻烦。
二
数据集
(补充:ObjectDataSourse,数据对象中的一种,其他的我没用过。
绑定的方法,可以是上面的BLL层,最初学net的时候,学的是ObjectDataSourse绑定数据集)
。
数据集,实现了强类型DataSet。比手写ADO.net好就是这一点,可以不再用row["string"]这种方式取了,能把查询的结果转换为强类型,可以.出相应的属性(字段)。
其他和ADO.NET的 DLL层差不多,能定义方法写SQL。
缺点是SQL表之前的的连接不方便,优点是能转为强类型对象,数据集类能返回一个适配器对象,这个对象的实际是数据集内部类的实例。
表连接这里,我没用过,不知道其他人怎么用的,我只用到单表数据返回强类型,多表关连,得以A表查各的数据为参数再另外查询B表。
现在的三层架构代码生成器里有Tolist方法, 也可以把表转为强类型,也同样是单表。数据集和代码生成器差不多,实现方法也差不多,比纯ADO.NET,多了个TOLIST,转为MODEL类对象。
数据集和DLL层的TOlIST方法,都要有一个实体类的参于来实现,也算是简单的ORM,但多表联接是硬伤。
这个实体对象,点不出关联对象,得不到关联对象的属性。
三
ORM框架
高级的ORM框架,实现了,表与表,实体对象与实体对象的关联。
JAVA的hibernate(net移植为Nhibernate)和.net下的EF。
1:hibernate,
因为对ssh很好奇,工作之余自学了SSH,因此接触到了hibernate,来京找java方面的工作因缺少经验等比较着争等原因没找到,便又作回了net,在net里有相似的NHibernate。
2:linq to sql和EF
linq to sql已经不再支持,但依然可以学习,因为EF的查询语法和LINQ大多是相似的。
EF比LTS的性能高,可以参照LTS学习EF的查询语法。当然,小的项目,没有太多关系的小表(就算全部读到内存也不占多少地方,当然linq to sql声明过的对象,EF就得在另外的命名空间声明)还是可以用LTS的。
hibernate和EF的区别
关系配置:hibernate是通过XML配置,非侵入(不在代码里),EF是写在代码里,用特性实现(写在代码里)。
查询语句:hibernate用HQL,有SQL基础的学这其实不用多少功夫,只人注意几个特别的关键字 和以及查询结果和配置的关系,一个月左右,有问题查文档就可以熟悉了诸如fetch。缺点是没有编译时提示,可能会拼错。
hibernate还可以用ICriteria查询,完全面向对象,这个我还没真正用过,不过在一篇安卓的课程里见过。
EF linq,会linq linq to sql的再学来很容易,要拓展的时候则要注意,Linq的优点是,写代码时就可以查错。
看博客了解到Nhibernate有一个拓展DLL,实现了Linq查询。
缓存:hibernate原生实现了缓存。
事务:
最后一个就不是这两种技术的问题,而是支持问题了。
支持EF的数据库不多,或为有限支持。EF也只用于.net环境。
而hibernate,JAVA环境都可以使用,安卓上层开发用的JAVA,数据访问层和hibernate类似。
目前也是在学习熟悉中