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) ...
随机推荐
- js之dom_2
动态脚本1 载入脚本文件 var s = document.createElement("script"); s.src = "test2.js"; s.typ ...
- ElasticSearch在Azure中的集群配置和Auto-Scale
最近在项目中ElasticSearch的使用越来越多,最新的项目中要求ES使用集群,在啥都不知道的情况下弄了两天后,终于搞定,因此写个笔记记录下. 1.首先我们需要创建一个Virtual networ ...
- MVC+Ef项目(3) 抽象数据库访问层的统一入口;EF上下文线程内唯一
抽象一个数据库访问层的统一入口(类似于EF的上下文,拿到上下文,就可以拿到所有的表).实际这个入口就是一个类,类里面有所有的仓储对应的属性.这样,只要拿到这个类的实例,就可以点出所有的仓储,我们在 R ...
- WEBUS2.0 In Action - 搜索操作指南 - (4)
上一篇:WEBUS2.0 In Action - 搜索操作指南(3) 6. 搜索多个索引 为了提升性能, 我们可以从多个索引同时进行搜索, Webus.Search.MultiSearcher提供了相 ...
- BZOJ 1878 HH的项链
不能分块(显然复杂度会炸啊.....) 离线+BIT.每个颜色在每个询问中只出现一次. #include<iostream> #include<cstdio> #include ...
- foreach的指针问题
从代码: $arr = array(,,,,); echo '$arr = array(1,2,3,4,5)','<br>'; foreach($arr as $key => &am ...
- swun 1766 我的悲剧不可能那么好数
解题思路: 一向提交特别慎重的我,这题竟然PE了5发左右,放了几天,再回来写,直接1A, 相当的自豪,而且是最优解题者.这题千万要注意,化繁为简,文章只包括大小 写字母和数字,还有空行. #inc ...
- Android Studio 学习 - 基本控件的使用;Intent初学
Android Studio学习第三天. 今天主要学习 1. RadioButton.CheckBox.RatingBar.SeekBar等基础控件的使用. 结合Delphi中相类似的控件,在这些基本 ...
- HDU 4741
获得 新的模板了/// 此模板 有线段和线段的最短距离方法,同时包含线段与线段的最短距离:#include<iostream> #include<stdio.h> #inclu ...
- ORACLE执行计划 explain说明
ORACLE SQL优化工具系列之--EXPLAIN PLAN 对于oracle数据库来说,sql语句的优化可能是对性能提升最为明显的,当然对于DBA来说,也是挑战性比较大的.为了优化一个复杂的SQL ...