ado通用操作数据单元
DELPHI开发2层C/S数据库应用程序,许多人通过ADOQUERY或ADOTABLE直接操作数据库,其实这种方法虽然最为直接,但有其缺点:如果以后要将程序升级为3层C/S会非常困难。而通过像下面的通用数据操作方法,像开发3层C/S一样地开发2层C/S程序,通过ADOQUERY或ADOTABLE获取数据,通过DATASETPROVIDER转换数据格式为OLEVARIANT,通过CLIENTDATASET内存数据集再同客户端显示控件关联,则所有操作数据的方法高度集中统一,以后要升级为多层会非常容易。这就是间接所带来的高度灵活。
ADO不能像FIREDAC和UNIDAC一样提交联表查询的CLIENTDATASET.DELTA,这在保存类似“单据”的数据的时候很不方便,需要间接一下然后才能提交。
FIREDAC和UNIDAC虽然默认也不支持,但只要设置属性就能获得支持。
其中FIREDAC的设置:UpdateOptions.CheckReadOnly:=False
其中的原由:A表联接B表查询,CLIENTDATASET中的字段既有A表的也有B表的,试图将CLIENTDATASET.delta提交给A表,CLIENTDATASET.delta将B表的字段值改变也一块打包了,而B表的字段的readonly:=true,试图提交只读字段会报错。
unit untDB;
interface
uses
System.SysUtils, System.Classes, Data.DB, Data.Win.ADODB, Datasnap.Provider,
System.Variants, Vcl.Forms;
type
TfrmDB = class(TDataModule)
ADOConnection1: TADOConnection;
qryQuery: TADOQuery;
DataSetProvider1: TDataSetProvider;
qryExecute: TADOQuery;
procedure DataModuleCreate(Sender: TObject);
procedure qryQueryBeforeOpen(DataSet: TDataSet);
procedure qryQueryAfterOpen(DataSet: TDataSet);
private
{ Private declarations }
procedure connectDB;
public
{ Public declarations }
function querySQL(const sql: string): OleVariant;
function executeSQL(const sql: string): Boolean;
function saveData(const tableName: string; delta: OleVariant): Boolean;
function SaveDatas(tableNames, deltas: OleVariant;
tableCount: Integer): Boolean;
end;
var
frmDB: TfrmDB;
implementation
{ %CLASSGROUP 'Vcl.Controls.TControl' }
uses UnitWait;
{$R *.dfm}
{ TfrmDB }
procedure TfrmDB.connectDB;
begin
ADOConnection1.Close;
ADOConnection1.ConnectionString := 'FILE NAME=' +
ExtractFilePath(Application.ExeName) + 'db.udl';
try
ADOConnection1.Connected := True;
except
on E: Exception do
raise Exception.Create(E.Message);
end;
end;
procedure TfrmDB.DataModuleCreate(Sender: TObject);
begin
connectDB;
end;
function TfrmDB.executeSQL(const sql: string): Boolean;
begin
Result := False;
if sql = '' then
Exit;
qryExecute.Close;
qryExecute.sql.Clear;
qryExecute.sql.Text := sql;
Result := qryExecute.ExecSQL > 0;
end;
procedure TfrmDB.qryQueryAfterOpen(DataSet: TDataSet);
begin
FormWait.Close;
FormWait.Free;
end;
procedure TfrmDB.qryQueryBeforeOpen(DataSet: TDataSet);
begin
FormWait := TFormWait.Create(Application);
FormWait.Show;
FormWait.Update;
end;
function TfrmDB.querySQL(const sql: string): OleVariant;
begin
Result := null;
if sql = '' then
Exit;
qryQuery.Close;
qryQuery.sql.Clear;
qryQuery.sql.Text := sql;
qryQuery.Open;
Result := DataSetProvider1.Data;
end;
function TfrmDB.saveData(const tableName: string; delta: OleVariant): Boolean;
var
errCnt: Integer;
begin
Result := False;
if (tableName = '') or VarIsNull(delta) then
Exit;
qryQuery.Close;
qryQuery.sql.Clear;
qryQuery.sql.Text := 'select * from ' + tableName + ' where 1=2';
qryQuery.Open;
DataSetProvider1.ApplyUpdates(delta, 0, errCnt);
Result := errCnt = 0;
end;
function TfrmDB.SaveDatas(tableNames, deltas: OleVariant;
tableCount: Integer): Boolean;
var
i, errCnt: Integer;
begin
if not ADOConnection1.InTransaction then
ADOConnection1.BeginTrans; // 开启事务
try
for i := 0 to tableCount - 1 do
begin
qryQuery.Close;
qryQuery.sql.Clear;
qryQuery.sql.Text := 'select * from ' + tableNames[i] + ' where 1=2';
qryQuery.Open;
DataSetProvider1.ApplyUpdates(deltas[i], 0, errCnt);
end;
ADOConnection1.CommitTrans; // 提交事务
Result := True;
except
ADOConnection1.RollbackTrans; // 回滚事务
Result := False;
end;
end;
end.
ado通用操作数据单元的更多相关文章
- EsayUI + MVC + ADO.NET(工作单元)
关联的设计 关联本身不是一个模式,但它在领域建模的过程中非常重要,所以需要在探讨各种模式之前,先讨论一下对象之间的关联该如何设计.我觉得对象的关联的设计可以遵循如下的一些原则: 关联尽量少,对象之间的 ...
- Delphi项目构成之单元文件PAS
单元文件是Pascal源文件,扩展名为.pas. 有三种类型的单元文件: 窗体/数据模块和框架的单元文件(form/data module and frame units),一般由Delphi自动生成 ...
- MVC+EF 理解和实现仓储模式和工作单元模式
MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generi ...
- 【转】Delphi多线程学习(9):多线程数据库查询(ADO)
原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用 ...
- 教程-Delphi多线程数据库查询(ADO)
ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoIniti ...
- Delphi多线程数据库查询(ADO)
ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoIniti ...
- ADO多线程数据库总结
ADO多线程数据库查询通常会出现以下问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoIniti ...
- 多线程数据库查询(ADO)
ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoIniti ...
- ADO多线程数据库查询
{ADO查询多线程单元} unit ADOThread; interface uses Classes,StdCtrls,ADODB; type TADOThread = class(TThread) ...
随机推荐
- UVa 424 Integer Inquiry
之前杭电上也做过a + b的高精度的题,不过这道题的区别是有多组数据. 之前做的时候开了3个字符数组a,b,c,在计算的时候还要比较a,b长度,短的那个还要加'0',还设置了一个add来存放进位. 现 ...
- 【同行说技术】iOS程序员从小白到大神必读资料汇总
在文章<iOS程序员从小白到大神必读资料汇总(一)>里面介绍了很多iOS入门学习的资料,今天小编就发几篇技术进阶的文章,快来看看吧! 一.iOS后台模式开发指南 这个教程会教你在什么时候怎 ...
- 内存泄露(OOM)现象及举例
一.HeapSize OOM(堆空间内存溢出) A.eg:List.add(" ")在一个死循环中不断的调用add却没有remove. B.并发导致. 解决方法有:1.代码提速.这 ...
- Java中sychronized方法与sychronized块区别
一.举几个栗子
- 【转】Undefined symbols for architecture i386:和"_OBJC_CLASS_$_xx", referenced from:问题解决方法
多个人共同操作同一个项目或拷贝项目时,经常会出现类似这样的问题: Undefined symbols for architecture i386: "_OBJC_CLASS_$_xx文件名& ...
- SQL0668N 由于表 "db2inst1.test" 上的原因代码 "3",所以不允许操作(解因为LOAD引起的LOAD暂挂状态锁)
DB2解因为LOAD引起的LOAD暂挂状态锁 一般解锁命名是,SET INTEGRITY FOR temp_test IMMEDIATE CHECKED 但是load暂挂状态是解不了的,可以l ...
- B-树和B+树
B-树和B+树是一种平衡的多路查找树,它在文件系统中很有用.一颗m阶的b-树,或为空树,或满足下列特性的m叉树.1)树中每个节点至多有m棵子树2)若根结点不是叶子结点,则至少有两棵子树.3)除根之外的 ...
- hdu 2899(数学基础+二分)
题意:给了你一个函数,然后给了你x的变化范围,让你求出函数的最小值. 分析:它让你求的是函数的最小值,所以我们可以先对函数求导,得到的导数就可以判断函数的单调性了,求出导数后,我们发现如果函数的导数是 ...
- Android基于XMPP Smack openfire 开发的聊天室
Android基于XMPP Smack openfire 开发的聊天室(一)[会议服务.聊天室列表.加入] http://blog.csdn.net/lnb333666/article/details ...
- 企业网站DDOS防护解决方案
随着网络的普及,越来越多的企业开始了上网之路,由于网络安全知识的欠缺,很多企业以为做一个网站就 等于 网络化了,于是狠花血本请专业网络公司制作出各种漂亮的网页.但做完才发现,网络上的各种漏洞的DDOS ...