Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

TDatabase & DLL

Posted on 1999-07-30
9
Medium Priority
?
404 Views
Last Modified: 2010-04-04
I'd like to create an EXE file with a TDatabase, connect it to an IB db, and share the same connection with a DLL that will contain some TQuerys.
The question is: is it possible ? and if it is how ?
I've tried something (passing TDatabase, Databasename.. as parameters) but whenever (in the DLL) i opened the TQuery i was
prompted for login; (so I think he was doing another connection).
0
Comment
Question by:isabella
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
9 Comments
 

Author Comment

by:isabella
ID: 1391981
Edited text of question.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1391982
Does setting the LoginPrompt property of TDatabase to false help?

Regards,

Epsylon.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 1391983
hi isabella
verify that the session is the same
meikl
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Expert Comment

by:nitdgrev
ID: 1391984
hi isabella,

kretzschmar is right.  In order to avoid getting this login prompt I've found that you have to set the dll session object to the main session, ie pass Session : TSession to your dll..  

Although this works in maintaining the main exe's connection and eliminates the logon prompt, I have found that this may introduce access violations within your dll.

There is currently a question posted by 'Westy', ie Q10188932, after the same result you are.  

Let me know if you can dodge the access violations...

...NITDGREV...
0
 
LVL 15

Expert Comment

by:simonet
ID: 1391985
Synchronize a DLL to an Open Dataset

This document demonstrates how to use Object Pascal to link a
DLL dynamically, on-the-fly, into an active Database, thus, giving the
Developer the ability to 'Modularize' features. (Whether at Run-Time or
Design-Time)

The technique of linking a DLL Dynamically into an EXE is useful in
many cases.  Examples include, an Accounting package which offers several
'plug-in' modules (A/R, A/P, General Ledger, etc.) or a Point of Sale
package with Current Stock, FIFO/LIFO Ordering, Vendor Tracking, etc.,
modules.

This TI will provide a solid example of how to do this with one
dll, 'Editdll.dll', but will give the Developer the essentials leading
to extensive modularation in projects.

Prerequisites:
--------------
Familiarity with the TTable component, DLL usage, BDE API, and
BDE hCursor knowledge. *WIN API for Dynamical loading of any DLL's.


                          SAMPLE APPLICATION

The following form, EditForm, is based on the COUNTRY table in the
DBDEMO's directory.  When the user presses the 'Edit' button or
double-clicks a record (row), a dialog box appears, from 'EditDll.dll',
displaying record specific information. At this point, the DLL has
synchronized itself not only with the dataset (& session) but also with
the current record. This mean's, the user can now modify the same data
EditForm is viewing! So, with no ado, let's delve into the sample code.
(For best results, simply cut and paste into appropriate files)

>Main Form Project<
-------------------

{ MAINDB.DPR }
program maindb;

uses
  Forms,
  mainform in 'mainform.pas' {DBMainForm};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TDBMainForm, DBMainForm);
  Application.Run;
end.

>>

{ MAINFORM.PAS }
unit mainform;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  StdCtrls, Forms, DBCtrls, DB, DBGrids, DBTables, Grids, ExtCtrls,
  BDE;

type
  TDBMainForm = class(TForm)
    Table1Name: TStringField;
    Table1Capital: TStringField;
    Table1Continent: TStringField;
    Table1Area: TFloatField;
    Table1Population: TFloatField;
    DBGrid1: TDBGrid;
    DBNavigator: TDBNavigator;
    Panel1: TPanel;
    DataSource1: TDataSource;
    Panel2: TPanel;
    Table1: TTable;
    EditButton: TButton;
    procedure FormCreate(Sender: TObject);
    procedure EditButtonClick(Sender: TObject);
    procedure DBGrid1DblClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  DBMainForm: TDBMainForm;

implementation

{$R *.DFM}

procedure TDBMainForm.FormCreate(Sender: TObject);
begin
  Table1.Open;
end;

// {NOTES: DBHandle is a Handle to the Database & DSHandle is a cursor
//  to the record being viewed. Also, if the purpose is to dynamically
//  load a DLL at run-time, use the LoadLibrary, GetProcAddress, and
//  FreeLibrary API calls in place of the implicit load calls at startup.
//  An Example of the APIcalling convention is: }
// Type
//  {For GetProcAddress}
//  BDEDataSync =
//    function(const DBHandle: HDBIDB; const DSHandle: HDBICur): Boolean;
//             stdcall;
//  {For the trapping of DLL load error's}
//  EDLLLoadError = class(Exception);
// var h: hwnd;
//     p: BDEDataSync;
//     LastError: DWord;
// begin
// UpdateCursorPos;
// Try
//   h := loadLibrary('EDITDLL.DLL');
//   {NOTE to Delphi 1.0 users: Whereas Win32 LoadLibrary returns a
//    NULL if the DLL load was unsuccessful, thus requiring a call to
//    GetLastError to find the error, Win16 LoadLibrary returns
//    an error value (less than HINSTANCE_ERROR) which can be checked
//    in the Win16API SDK as to the reason for the failure.}
//   if h = 0 then begin
//      LastError := GetLastError;
//      Raise EDLLLoadError.create(IntToStr(LastError) +
//                                 ': Unable to load DLL');
//      end;
//   try
//      p := getProcAddress(h, 'EditData');
//      if p(DBHandle, Handle) then Resync([]);
//   finally
//      freeLibrary(h);
//   end;
// Except
//   On E: EDLLLoadError do
//     MessageDLG(E.Message, mtInformation, [mbOk],0);
// end;        
// end;
// {or}
function EditData(const DBHandle: HDBIDB; const DSHandle: HDBICur):
   Boolean;  stdcall external 'EDITDLL.DLL' name 'EditData';

procedure TDBMainForm.EditButtonClick(Sender: TObject);
begin
  with Table1 do
  begin
    UpdateCursorPos;
// Call the EditData Procedure from EditDll.dll.
    if EditData(DBHandle, Handle) then Resync([]);
  end;
end;

procedure TDBMainForm.DBGrid1DblClick(Sender: TObject);
begin
  EditButton.Click;
end;

end.

>>

>EDIT DLL PROJECT<
------------------

{ EDITDLL.DPR }
library editdll;

uses
  SysUtils,
  Classes,
  editform in 'editform.pas' {DBEditForm};

exports
  EditData;
 
begin
end.

>>

{ EDITFORM.PAS }
unit editform;

interface

uses
  SysUtils, Windows, Messages, Classes, Graphics, Controls,
  StdCtrls, Forms, DBCtrls, DB, DBTables, Mask, ExtCtrls, BDE;

type
  TTableClone = class;

  TDBEditForm = class(TForm)
    ScrollBox: TScrollBox;
    Label1: TLabel;
    EditName: TDBEdit;
    Label2: TLabel;
    EditCapital: TDBEdit;
    Label3: TLabel;
    EditContinent: TDBEdit;
    Label4: TLabel;
    EditArea: TDBEdit;
    Label5: TLabel;
    EditPopulation: TDBEdit;
    DBNavigator: TDBNavigator;
    Panel1: TPanel;
    DataSource1: TDataSource;
    Panel2: TPanel;
    Database1: TDatabase;
    OKButton: TButton;
  private
    TableClone: TTableClone;
  end;

{ TTableClone }

  TTableClone = class(TTable)
  private
    SrcHandle: HDBICur;
  protected
    function CreateHandle: HDBICur; override;
  public
    procedure OpenClone(ASrcHandle: HDBICur);
  end;

function EditData(const DBHandle: HDBIDB; const DSHandle: HDBICur):
                   Boolean; stdcall;

var
  DBEditForm: TDBEditForm;

implementation

{$R *.DFM}

{ Exports }

function EditData(const DBHandle: HDBIDB; const DSHandle: HDBICur):
                  Boolean; stdcall;
var
  DBEditForm: TDBEditForm;
begin
  DBEditForm := TDBEditForm.Create(Application);
  with DBEditForm do
  try
// Set the handle of the Database1 to that of the currently opened database
    Database1.Handle := DBHandle;
    TableClone := TTableClone.Create(DBEditForm);
    try
      TableClone.DatabaseName := 'DB1';
      DataSource1.DataSet := TableClone;
      TableClone.OpenClone(DSHandle);
      Result := (ShowModal = mrOK);
      if Result then
      begin
        TableClone.UpdateCursorPos;
        DbiSetToCursor(DSHandle, TableClone.Handle);
      end;
    finally
      TableClone.Free;
    end;
  finally
    Free;
  end;
end;

{ TTableClone }

procedure TTableClone.OpenClone(ASrcHandle: HDBICur);
begin
  SrcHandle := ASrcHandle;
  Open;
  DbiSetToCursor(Handle, SrcHandle);
  Resync([]);
end;

function TTableClone.CreateHandle: HDBICur;
begin
   Check(DbiCloneCursor(SrcHandle, False, False, Result));
end;

end.

>>

{ EDITFORM.DFM }
object DBEditForm: TDBEditForm
  Left = 201
  Top = 118
  Width = 354
  Height = 289
  ActiveControl = Panel1
  Caption = 'DBEditForm'
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  Position = poScreenCenter
  PixelsPerInch = 96
  TextHeight = 13
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 346
    Height = 41
    Align = alTop
    TabOrder = 0
    object DBNavigator: TDBNavigator
      Left = 8
      Top = 8
      Width = 240
      Height = 25
      DataSource = DataSource1
      Ctl3D = False
      ParentCtl3D = False
      TabOrder = 0
    end
    object OKButton: TButton
      Left = 260
      Top = 8
      Width = 75
      Height = 25
      Caption = 'OK'
      Default = True
      ModalResult = 1
      TabOrder = 1
    end
  end
  object Panel2: TPanel
    Left = 0
    Top = 41
    Width = 346
    Height = 221
    Align = alClient
    BevelInner = bvLowered
    BorderWidth = 4
    Caption = 'Panel2'
    TabOrder = 1
    object ScrollBox: TScrollBox
      Left = 6
      Top = 6
      Width = 334
      Height = 209
      HorzScrollBar.Margin = 6
      HorzScrollBar.Range = 147
      VertScrollBar.Margin = 6
      VertScrollBar.Range = 198
      Align = alClient
      AutoScroll = False
      BorderStyle = bsNone
      TabOrder = 0
      object Label1: TLabel
        Left = 6
        Top = 6
        Width = 28
        Height = 13
        Caption = 'Name'
        FocusControl = EditName
      end
      object Label2: TLabel
        Left = 6
        Top = 44
        Width = 32
        Height = 13
        Caption = 'Capital'
        FocusControl = EditCapital
      end
      object Label3: TLabel
        Left = 6
        Top = 82
        Width = 45
        Height = 13
        Caption = 'Continent'
        FocusControl = EditContinent
      end
      object Label4: TLabel
        Left = 6
        Top = 120
        Width = 22
        Height = 13
        Caption = 'Area'
        FocusControl = EditArea
      end
      object Label5: TLabel
        Left = 6
        Top = 158
        Width = 50
        Height = 13
        Caption = 'Population'
        FocusControl = EditPopulation
      end
      object EditName: TDBEdit
        Left = 6
        Top = 21
        Width = 135
        Height = 21
        DataField = 'Name'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 0
      end
      object EditCapital: TDBEdit
        Left = 6
        Top = 59
        Width = 135
        Height = 21
        DataField = 'Capital'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 1
      end
      object EditContinent: TDBEdit
        Left = 6
        Top = 97
        Width = 135
        Height = 21
        DataField = 'Continent'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 2
      end
      object EditArea: TDBEdit
        Left = 6
        Top = 135
        Width = 65
        Height = 21
        DataField = 'Area'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 3
      end
      object EditPopulation: TDBEdit
        Left = 6
        Top = 173
        Width = 65
        Height = 21
        DataField = 'Population'
        DataSource = DataSource1
        MaxLength = 0
        TabOrder = 4
      end
    end
  end
  object DataSource1: TDataSource
    Left = 95
    Top = 177
  end
  object Database1: TDatabase
    DatabaseName = 'DB1'
    LoginPrompt = False
    SessionName = 'Default'
    Left = 128
    Top = 176
  end
end

>>



0
 

Author Comment

by:isabella
ID: 1391986
I've read this Borland TI, but the problem is not to
share a dataset but a database !
0
 
LVL 15

Expert Comment

by:simonet
ID: 1391987
Ok, now I see.

Well, the only way I know of doing it is to create a permanent database alias, which will be known by both the main EXE and the DLL. You can create database alias in runtime, so no extra setup is necessary. Here's the code for doing that:

http://www.bhnet.com.br/~simonet/tipstricks/alias.htm

There will be 2 different TDatabase components, but both will point to the same database alias. Other than that it's not possible to share a TDatabase.

My suggestion is that you create the alias from the EXE, before the DLL is loaded (it will have to be dynamically loaded). The name of the database (the alias) can be hardcoded in the DLL and in the EXE.

Yours,

Alex
Athena's Place: http://www.bhnet.com.br/~simonet
0
 
LVL 15

Accepted Solution

by:
simonet earned 200 total points
ID: 1391988
I found it!

Here's the URL with the solution:

http://www.undu.com/DN960801/00000012.htm

Yours,

Alex
0
 
LVL 1

Expert Comment

by:Moondancer
ID: 6872280
GREETINGS!

This question was awarded, but never cleared due to the JSP-500 errors of that time.  It was "stuck" against userID -1 versus the intended expert whom you awarded.  This corrects the problem and the expert will now receive these points; points verified.

Please click on your Member Profile and select "View Question History" to navigate through any open or locked questions you may have to update and finalize them.  If you are an EE Pro user, you can also choose Power Search to find all your open questions.

This is the Community Support link, if help is needed, along with the link to All Topics which reflects many TAs recently added.

http://www.experts-exchange.com/jsp/qList.jsp?ta=commspt
http://www.experts-exchange.com/jsp/zonesAll.jsp
 
Thank you,
Moondancer
Moderator @ Experts Exchange
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question