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.

时间: 2024-07-30 11:08:56

ado通用操作数据单元的相关文章

MVC+EF 理解和实现仓储模式和工作单元模式

MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generic Repository in ASP.NET MVC using Entity Framework 文章介绍 在这篇文章中,我们试着来理解Repository(下文简称仓储)和Unit of Work(下文简称工作单元)模式.同时我们使用ASP.NET MVC和Entity Framework 搭

Delphi多线程数据库查询(ADO)

ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoInitialize和CoUninitialize.调用CoInitialize失败会产生"CoInitialize was not called"例外. 2.画布不允许绘画(Canvas does not allow drawing):所以,必须通过Synchronize过程来通知主线程访问主窗体

【转】Delphi多线程学习(9):多线程数据库查询(ADO)

原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoInitialize和CoUninitialize.调用CoInitialize失败会产生"CoInitialize was not called"例外. 2.画布不允许绘画(Can

Delphi项目构成之单元文件PAS

单元文件是Pascal源文件,扩展名为.pas. 有三种类型的单元文件: 窗体/数据模块和框架的单元文件(form/data module and frame units),一般由Delphi自动生成. 组件的单元文件(component units),由您或者Delphi生成. 通用的单元文件(general-purpose units),有您创建. 下面让我们看看基本的Pascal单元文件结构是如何的? Step1.在主菜单上选择[File | New | Unit],Delphi将创建一个

ADO多线程数据库查询

ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用 (CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoInitialize和CoUninitialize.调用CoInitialize失败会产生"CoInitialize was not called"例外. 2.画布不允许绘画 (Canvas does not allow drawing):所以,必须通过Synchronize过程来通知主线程访问主

ADO.NET开发技巧(5)-第二种方法

第二种用ado.net操作数据的方式是采用DataSet和DataAdapter.它是用Adapter类读取数据在把数据存储在DataSet中.具体代码如下: private void BindData() { string comnStr = @"data source=BLACKERXHUNTER\SQLEXPRESS;initial catalog=StudyUse; integrated security = True;"; using (SqlConnection conn

Systemd详解之单元配置systemd.unit

英文网址:https://www.freedesktop.org/software/systemd/man/systemd.unit.html 名称 systemd.unit - systemd 单元配置 概要 service.service, socket.socket, device.device, mount.mount, automount.automount, swap.swap, target.target, path.path, timer.timer, slice.slice,

[delphi技术]Delphi多线程数据库查询(ADO)

ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoInitialize和CoUninitialize.调用CoInitialize失败会产生"CoInitialize was not called"例外. 2.画布不允许绘画(Canvas does not allow drawing):所以,必须通过Synchronize过程来通知主线程访问主窗体

第四章 1.文件介绍

项目文件 *.dpr project project1 uses Forms, Unit1 in 'unit1.pas' {Form1} {$R *.res}  -- 调用同名的资源文件 {$R MyRes.res} --也可以是自己编辑的资源文件  也在这里调用 begin Application.Initialize; Application.CreateForm(TForm1,Form1);    --中间可以添加自己需要的代码,一般来说不需要编译 Applicatipn.Run; end