Showing posts with label Delphi. Show all posts
Showing posts with label Delphi. Show all posts

Thursday, October 5, 2017

Diamond Problem in Multiple Inheritance in OOPS

The diamond problem occurs when two super classes of a class have a common base class. 

Suppose there are four classes A, B, C and D. Class B and C inherit class A. Now class B and C contains one copy of all the functions and data members of class A. Class D is derived from class B and C. Now class D contains two copies of all the functions and data members of class A. One copy comes from class B and another copy comes from class C.

Let’s say class A has a function with name display(). So class D have two display() functions as I have explained above. If we call display() function using class D object then ambiguity occurs because compiler gets confused that whether it should call display() that came from class B or from class C. If you will compile above program then it will show error.

This kind of problem is called diamond problem as a diamond structure is formed (see the image).

That is why major programming languages like C#, Java and Delphi don't have multiple inheritance because it can lead to diamond problem and rather than providing some complex way to solve it, there are better ways through which we can achieve the same result as multiple inheritance. We can use interfaces to resolve this problem.

C++ supports multiple inheritance.

Notice that the above problem with multiple class inheritance can also come with only three classes where all of them has at least one common method.

Because of this problem we can not extend two classes for implementing multiple inheritance and to resolve this problem of multiple inheritance in object oriented programming we use interfaces for implementing the functionality of multiple inheritance. 

As we know we do not define a function but only declare that function in an interface. So if we use interfaces we can extend one class and one or more interfaces or we can implement more than one interfaces at a time to use the functionality of multiple inheritance and we can escape from diamond problem.

Thursday, September 28, 2017

How to declare Static/Class variables, properties, functions and procedures in Delphi?

In Delphi, we do have static variables, properties, functions and procedures, but instead of the word "static" we refer the word "class". In this tutorial, I have shown the syntax of declaring the static variables, properties, functions and procedures in Delphi. We don't have to use "static" keyword while declaring the static variables and properties, just use "class" keyword. While declaring static functions and procedures, we have to use both "class" and "static" keyword.

Declare a static/class variable in Delphi

type
  TStaticDemoClass = class(TObject)
  public
    class var StaticVar: integer;
  end;
Declare a static/class property in Delphi

type
  TStaticDemoClass = class(TObject)
  private
    class var FStaticVar: integer;
  public
    class property StaticVar: integer read FStaticVar write FStaticVar;
  end;

Now we can use above StaticVar variable/property anywhere in the unit like this:
procedure TForm1.Button1Click(Sender: TObject);
var a:integer;
begin
  TStaticDemoClass.StaticVar := 1;
end;

We can also use static/class functions and procedures in Delphi. Below example, I have copied from documentation:

type
  TMyClass = class
    strict private
      class var FX: Integer;
    strict protected  
      //Note: accessors for class properties must be declared class static.
      class function GetX: Integer; static;
      class procedure SetX(val: Integer); static;
    public
      class property X: Integer read GetX write SetX;
      class procedure StatProc(s: String); static;
  end;

TMyClass.X := 17;
TMyClass.StatProc('Hello');

You need to use "static" keyword after function / procedure declaration. Classes can have static class methods -- i.e. methods that can be called from a class type. Class static methods can be accessed without an object reference. Unlike ordinary class methods, class static methods have no Self parameter at all. They also cannot access any instance members. They still have access to class fields, class properties, and class methods. Also unlike class methods, class static methods cannot be declared virtual.

Tuesday, September 26, 2017

VCL Hierarchy in Delphi: Types of Controls in Delphi: TWinControls and TGraphicControls

In VCL (Visual Component Library) hierarchy, you will find TObject at the top, then TPersistent, then TComponent and then TControl.

TObject >> TPersistent >> TComponent >>TControl

VCL Hierarchy in Delphi
TObject is the base class from which all classes descend.

TPersistent class descends directly from TObject. The special characteristic of TPersistent is that it is an abstract class that defines the methods that allow it to be streamed.

TComponent is the base class from which all components descend. Non-visual components are descendants of TComponent. For example: TTimer

TControl is the base class from which all the visual components descend. For example: TEdit, TListBox, TComboBox etc.

Again, there are two types of controls (TControl): Window Controls (TWinControl) and Graphic Controls (TGraphicControl)

Following is the difference between TWinControl and TGraphicControl in Delphi:

TWinControls

TWinControls can receive input focus and they can be parents to other controls.

Example: TEdit, TListBox and TComboBox

TGraphicControl

TGraphicControls differ from TWinControls in that they cannot receive input focus. Also, they cannot be parents to other controls.

Example: TLabel

TGraphicControls are used when you want to display something on the form.

Two key advantages of TGraphicControls over TWinControls:

1. TGraphicControls don't use up system resources since they don't require a window handle.

2. They are a bit faster at drawing than their TWinControl counterparts since their painting is not subject to the windows message dispatching system. Instead, they piggyback on their parent's paint process.

For more details, please refer to documentation.

Friday, September 5, 2014

Difference between Free and FreeAndNil in Delphi: What to use when?

Difference between Free and FreeAndNil in Delphi: What to use when?

Free and FreeAndNil are the main concepts of memory management in Delphi. FreeAndNil is a function declared in the SysUtils unit and was introduced in Delphi 5. Below is the implementation of FreeAndNil:

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

Difference between Free and FreeAndNil: 

FreeAndNil first sets the object reference to nil and then frees the object. 

When to use FreeAndNil instead of Free?

If you want a rational answer, the question to ask is, why would you want to set an object reference to nil once you’re done with it?  And there’s only one good reason to ever do that: If you want to reuse the variable later.  There are some times when you’ll have an object that may or may not be initialized. If it’s not, then the variable will be nil, and if you find it’s nil, then you create it before using it.  This is a pretty common pattern.  It’s called “lazy creation”.  But every once in a while, you want to use lazy creation on an object, then destroy it and create it again. This is when FreeAndNil comes in handy.

Use FreeAndNil for Defensive Programming

You can compare FreeAndNil with seat (safety) belts in cars: if you application runs normally - then FreeAndNil won’t be useful. But if your code mess up with something - then FreeAndNil (as seat belts too) will protect you from consequences. By clearing the reference, FreeAndNil will help you to catch your wrong access immediately. Without it (i.e. by using Free only), your code may continue to run (even without raising an exception) and will give the wrong results or damage global state. It is quite dangerous situation and may lead to corrupt your data too. By not setting it to nil (in case of Free)- you're lying to the compiler. You're telling that there is allocated memory at this location, and the truth is that it isn't. And lying to machine just isn't good. FreeAndNil is very strict in these situation will immediately give you Access Violation error which I think is good thing and you can fix the problem on the spot because you know the problem!! Compare this with case, when your code silently produce wrong results! By always using FreeAndNil you’ll make your code bullet-proof for modifications.

Example of FreeAndNil

var
  myList : TList;
begin
  try
    myList := TList.Create;
    ....
    ....
  finally
    FreeAndNil(myList);
  end;
end;

Sunday, August 31, 2014

Difference between Override and Reintroduce in Delphi

Difference between Override and Reintroduce in Delphi

When you decide to declare a method as virtual, you are giving permission to derived classes to extend and override the method with their own implementation.

Use the reintroduce keyword to introduce a new implementation of a parent method (this hides the parent method). You can hide a method without using reintroduce but you will get a compiler warning. Using reintroduce will suppress the warning.

You tell the compiler that you know that you hide the ancestor function and replace it with this new function and do so deliberately.

Difference between Override and Reintroduce

1. The reintroduce and override modifiers have different meanings. The reintroduce modifier creates a new member with the same name, signature, and visibility and hides the original member. The override modifier extends the implementation for an inherited member and allows you to implement inheritance-based polymorphism.

2. Override is used in conjuction with Virtual/Dynamic methods of parent class but for Reintroduce, parent method should not be necassarily Virtual/Dynamic. 

The only reason to override an ancestor method is that you can call inherited from within the descendent method. If you don't intend to call inherited from within a descendent method, the descendent method should be declared with Reintroduce rather than Override.

Avoid Reintroduce

Sometimes there are clear reasons to introduce a new method with the same name, signature, and visibility of a parent method. In those clear cases, introducing a new member is a powerful feature. However, if you do not have a clear reason, then avoid using Reintroduce.

Saturday, August 30, 2014

Difference between Virtual, Dynamic and Abstract methods in Delphi

Difference between Virtual, Dynamic and Abstract methods in Delphi

Virtual and Dynamic methods are the strong concepts of Polymorphism in Delphi. Dynamic is semantically equivalent to Virtual. Both Virtual and Dynamic directives allows a class method to be override (replaced) by a same named method in a derived class. 

You would mark a function or procedure as Virtual or Dynamic when you allow a programmer who creates a class based on your class to replace its functionality. 

Virtual and Dynamic may be followed by the Abstract directive. This modifies the effect of the Virtual and Dynamic directives. It means that the current class must not code the method - it is there only as a placeholder to remind and ensure that derived classes implement it.

Difference between Virtual and Dynamic methods in Delphi

Although Virtual and Dynamic methods appear same but there is some differnce in their internal implementation. Virtual methods are implemented with a Virtual Method Table (VMT). There is one VMT for each class. The VMT contains one entry for each virtual method in the class. And that entry is the address of the method.

This allows for very efficient calling. You simply get the address of the VMT which is located at a fixed offset from Self. Then you look up the method pointer by index and call the method.

What this does mean is that if you have a class with a lot of virtual methods, and you derive a sub-class, you will make a brand new VMT with all the virtual methods. And if you have not overridden many of them, then you'll find that the VMTs have a lot of overlap.

This used to matter in the days of 16 bit. The VMTs could take up a lot of space in the executable image (that's what is meant by code size) and you could run out of space for the VMTs. So dynamic methods were introduced. The analogue to the VMT is the dynamic method table, DMT. This is implemented differently to avoid the repetition when methods are not overridden. The downside is that calling dynamic methods is more expensive.

In modern times, since 32 bit, and especially with the very fat executables that Delphi produces, these size issues don't matter. And so all sound advice is to use virtual methods exclusively.

Abstract methods must be virtual or dynamic

Any abstract method should be virtual or dynamic. For example:

function Age: Integer; Abstract;

will not work and throw following error:

E2167 Abstract methods must be virtual or dynamic

Conclusion: Virtual methods are optimized for speed and dynamic methods are optimized for size. In most of the situations, speed is more crucial than size, so I would prefer to use Virtual methods.

Friday, August 29, 2014

Difference between Owner and Parent in Delphi

Difference between Owner and Parent in Delphi

Parent is the Window control where the control is displayed. Owner is the component responsible for making sure it's destroyed. Parent refers to the component that another component is contained in, such as TForm, TGroupBox or a TPanel. If one control (parent) contains others, the contained controls are child controls of the parent.

Example of Owner and Parent

Whenever we try add a button on a panel in a form, we try to make an invisible connection between the components. When a component is dropped on a form at design time, the owner is the form and the parent is the container on which it is dropped.

As we add the button on the panel, the panel automatically is set as the parent of the button while the form becomes the owner.  

Another example, drop a group box on a form. Its owner and parent are both the form. Drop a check box on the group box. Its owner is the form and its parent is the group box.

Parent is required to make a control visible

For a component to be visible, it must have a parent to display itself within. Controls that appear on the screen need to know where to paint themselves, hence the parent property. It specifies the visual container for the control. This property must be specified before a control can be displayed. When you want to create a TButton at run-time, it is important that we remember to assign a parent - the control that contains the button. 

The Parent component on the other end determines how the child (i.e. contained component is to be displayed). All the properties like left, top etc are relative to the parent component.

Owner is Readonly while Parent can be changed

Owner property is a read only property and cannot be modified, however parent for a control can be assigned and chagned easily at runtime. The Owner is being set while invoking the create constructor and becomes a read-only property so can't be changed later on.

Allocating and Freeing the memory

The Owner component is responsible for freeing the allocated memory of the owned components. Form is the owner of all the components residing inside it. So whenever the form is destroyed, all the components memory is freed automatically. This is the purpose of ownership.

HasParent Property

Not all components have the Parent. Many forms do not have a Parent. For example, forms that appear directly on the Windows desktop have Parent set to nil. A component's HasParent method returns a boolean value indicating whether or not the component has been assigned a parent.

Parent Property

We use the Parent property to get or set the parent of a control. If we try to create a new control, then we need to set the parent property of the control to make it visible. For example, 

Button1.Parent := Panel1;

Above code has set Panel1 as the parent of Button1.

Difference between Components and Controls in Delphi

Difference between Components and Controls in Delphi

Controls are the visible elements on the Delphi Forms to which you can focus and interact. All the controls are components and vice versa is not true. So we can say that Controls are the subset of Components in Delphi.

TComponent is the common ancestor of all component objects in Delphi. TControl is the abstract base class for all visual components. Everything that goes into the component palette is a Component. Everything that goes into the component and is something that the user of the program can control by using mouse or keyboard is a Control.

For example: TTimer component is a component that you can place on a form, but it is not visible to the end-user. So TTimer is only the component but not a control in Delphi. Other examples like TTimer are TXMLDocument, TDatabase, TQuery, TTable, TDataSet, TDataSource etc. These all components play a vital role but never appear in front of the end user.

A TEdit or TButton is visible and can be controlled by the user (you can add events to TEdit and TButton and with those events a user can actually focus/select/click on the TEdit and TButton components). So both TEdit and TButton are the components as well as controls in Delphi. 

A control takes up more resources than a component because a control needs extra info about how to draw itself.

Thursday, August 21, 2014

How to create and extract ZIP files in Delphi XE6?

How to create and extract ZIP files in Delphi XE6?

Delphi provides System.Zip unit for creating ZIP files. System.Zip unit contains a simple ZIP extractor and creator class named TZIPFile. TZIPFile class mainly has three methods which are used to create and extract zip files:

ZipDirectoryContents: Creates the zipped file
IsValid: Validates the zip file
ExtractZipFile: Extracts the zip file

Following is the code snippet in Delphi to create a zip file.

uses System.Zip;

TZIPFile.ZipDirectoryContents('C:\FolderToZip', 'C:\ZippedFolder.zip');

Following is the code snippet in Delphi to extract a zip files. 

uses System.Zip;

ZipFile := 'ZippedFolder.zip'; //This is my zip file
if TZipFile.IsValid(ZipFile) then //Validate zip file
begin
  TZipFile.ExtractZipFile(ZipFile, 'C:\DestinationDirectory'); //Extract the zip file
end
else
begin
  ShowMessage('Zip File is not valid');
end;

Friday, August 1, 2014

How to create XML document in Delphi XE4 using IXMLDOCUMENT and IXMLNODE?

How to create XML document in Delphi XE4 using IXMLDOCUMENT and IXMLNODE?

Following is the self explanatory code in Delphi XE4 to create XML document using IXMLDOCUMENT and IXMLNODE interfaces. You should have XMLIntf and XmlDoc units in your uses section. Following CreateXMLinDelphi Delphi procedure creates an XML named MyXML in D drive.

procedure CreateXMLinDelphi;
var
  XML : IXMLDOCUMENT;
  RootNode, CurNode : IXMLNODE;
begin
  XML := NewXMLDocument;
  XML.Encoding := 'UTF-8';
  XML.Options := [doNodeAutoIndent];
  RootNode := XML.AddChild('ParentNode');
  CurNode := RootNode.AddChild('ChildNode1');
  CurNode.Text := 'ChildNode Text 1';
  CurNode := RootNode.AddChild('ChildNode2');
  CurNode.Text := 'ChildNode Text 2';
  XML.SaveToFile('D:\MyXML.xml');
  ShowMessage('XML created successfully');
end;

The above code generates following XML document:

<?xml version="1.0" encoding="UTF-8"?>
<ParentNode>
  <ChildNode1>ChildNode Text 1</ChildNode1>
  <ChildNode2>ChildNode Text 2</ChildNode2>
</ParentNode>

How to create an XTR file from XML in Delphi XE4 using XML Mapper?

How to create an XTR file from XML in Delphi XE4 using XML Mapper?


By using Delphi XE4 RAD Studio, you can create an XTR file from the given XML file using XML Mapper. XML Mapper Tool is provided in RAD Studio XE4 under Tools -> XML Mapper.

Following are the steps to create an XTR file from XML in Delphi XE4 using XML Mapper:

1. Open the XML Mapper Tools from RAD Studio. 


Now load an XML. In my case I am loading following simple XML:

<?xml version="1.0" encoding="UTF-8"?>
<Parent>
  <Child1>ABC</Child1>
  <Child2>XYZ</Child2>
</Parent>

All the nodes will appear on the left section of XML Mapper.

2. Right click on left section and select "Select All Children" option. Transformation will be created on the middle section.

3. Right click on left section again and select "Create Datapacket from XML". You will see the generated datapacket on the right section of the XML Mapper.

4. Hit "Create and Test Transformation" button in the middle section of XML Mapper.

5. Right click on the right section and select "Clear". A popup will appear asking you "Save changes to Transformation to Datapacket?".

6. Click Yes and save that XTR file.

I got following XTR file corresponding to the above XML file:

<XmlTransformation Version="1.0"><Transform Direction="ToCds" DataEncoding="UTF-8"><SelectEach dest="DATAPACKET\ROWDATA\ROW" from="\Parent"><Select dest="@Child1" from="\Child1"/><Select dest="@Child2" from="\Child2"/></SelectEach></Transform><XmlSchema RootName="Parent"><![CDATA[<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Parent" type="ParentType"/>
  <complexType xmlns="http://www.w3.org/2001/XMLSchema" name="ParentType">
    <sequence>
      <element name="Child1" type="Child1Type"/>
      <element name="Child2" type="Child2Type"/>
    </sequence>
  </complexType>
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Child1" type="Child1Type"/>
  <simpleType xmlns="http://www.w3.org/2001/XMLSchema" name="Child1Type">
    <restriction base="xs:string"/>
  </simpleType>
  <element xmlns="http://www.w3.org/2001/XMLSchema" name="Child2" type="Child2Type"/>
  <simpleType xmlns="http://www.w3.org/2001/XMLSchema" name="Child2Type">
    <restriction base="xs:string"/>
  </simpleType>
</xs:schema>]]></XmlSchema><CdsSkeleton/><XslTransform/><Skeleton><![CDATA[<?xml version="1.0"?><DATAPACKET Version="2.0"><METADATA><FIELDS><FIELD attrname="Child1" fieldtype="string" WIDTH="3"/><FIELD attrname="Child2" fieldtype="string" WIDTH="3"/></FIELDS><PARAMS/></METADATA><ROWDATA/><METADATA><FIELDS><FIELD attrname="Child1" fieldtype="string" WIDTH="3"/><FIELD attrname="Child2" fieldtype="string" WIDTH="3"/></FIELDS><PARAMS/></METADATA><ROWDATA/></DATAPACKET>
]]></Skeleton></XmlTransformation>

Friday, July 4, 2014

EOleException error raised with message catastrophic failure or access is denied in Delphi

EOleException error raised with message catastrophic failure or access is denied in Delphi

While calling DLLs from my application using safecall, I was getting EOleException error raised with message catastrophic failure. When I switched to stdcall, I started getting EOleException error raised with message access is denied for some calls. So, I thought to dive deep into the root cause of the error and tried to understand what exactly EOleException is in Delphi?

As per documentation:

EOleException is the exception class for OLE automation errors that occur in methods or properties of an object.

EOleException is the exception class for errors specific to the OLE IDispatch interface.

EOleException is raised when an error occurs in the middle of a method call from IDispatch. EOleException is generated when a server receives a failure return value from a property or method that was called with the IDispatch interface Invoke method.

When an error occurs, objects invoked through IDispatch can return essential information about the exception, including the source of the error, error code, description, help file, and ID number for context-sensitive help. EOleException captures this information, and the error description and ID number (if available) are included in a message generated by the constructor; the other information is stored in the Source and HelpFile properties defined for EOleException and the ErrorCode property inherited from EOleSysError.

Solution:

1. Try catching the error

try
  ....
  ....
except 
  on e: EOleException do
  begin
    ....
    .... 
  end;  
end;

2. Ignore the error

To stop Delphi from breaking, you will need to configure Delphi to ignore the exception by telling it that the application will handle the exception. Go to Tools > Debugger Options, on the "Language Exceptions" tab add "EOleException". Ensure that it is ticked, which tells the Delphi environment to ignore the exception (and let the code run).

Friday, May 16, 2014

Delphi Coding Standards and Guidelines

Delphi Coding Standards and Guidelines

Below are some Delphi coding standards and guidelines mentioned which each Delphi developer should take care of. Anybody can code, but neat and clean coding is an art. I have tried to mention some Delphi coding standards and guidelines which I follow everyday. Following list includes use of proper naming convention and indentation, proper exception handling and resource management, usage of proper datatypes etc.

1. Use proper naming convention

Use proper naming conventions and provide meaningful names to classes, records, arrays, enumerated types, pointers and other variables so that code readability is maintained and other developers can easily understand your code.

2. Always maintain a clear indentation

Always leave two character spaces before writing the child statement. Here is the example.

if condition1 then
begin
    fist statement
    second statement
end;

3. Declare records/class names prefixed with 'T' character, pointer names prefixed with 'P' character and field names of the class should be prefixed with 'F' character. The name of the object of the class should be same as that of the class name except the 'T' character prefixed. Here is the example.

TMyRecord = record
    ID : integer;
    RecNo : integer
end;

TMyClass = class(TObject)
private
   FMyField1: Integer;
   FMyField2: Integer;
end;

MyClass = TMyClass;

PMyPointer = ^TMyClass;

4. Always use try/except and try/finally

Always use try/except to handle all kinds of exception which may be raised from your code. Always use try/finally to free up memory which you might have assigned in your code. 

5. Avoid the use nested "with" statement

Nested "with" statements are confusing and make the debugging very hard. It decreases the code readablility. Consider the following example.

with myQueryComponent do             
begin 
    .......
    .......
  with myQueryComponent2 do
  begin
  ......
......
  end;
end;

6. Try to avoid "exit" statement

Wherever possible, try to minimize the use of "exit" statement. When dealing with loops, try to end the loop with some condition and avoid the use of exit statement.

7. "case" statements should be neat and clean

When you are using "case" statements, try to keep less code in it. If your code grows in size, it is advisable to make a different procedure or function for it and just call that function/procedure.

8. Try to minimize the use of variants

Variants are commonly used when datatypes are generally unknown but as a responsible developer you must try to avoid its usage. Consider the following example.

with dsMyDataset do
begin
    Active := False;
    Params.ParamByName('ID').AsVariant := AnyID;
    Active := True;
end;

Here, if you know that AnyID variable will be integer in all cases, then you should avoid the use of "AsVariant" like following:

with dsMyDataset do
begin
    Active := False;
    Params.ParamByName('ID').AsInteger := AnyID;
    Active := True;
end;

9. Minimize the use of global variables

Always try to use less global variables in your unit and try to declare them locally where you want to use them.

Tuesday, May 13, 2014

How to Insert/Edit Rows in Firebird Dataset in Delphi using FIBPLUS Components?

How to Insert/Edit Rows in Firebird Dataset in Delphi using FIBPLUS Components?

You can insert a row and edit an existing row in firebird dataset in Delphi. I will use FIBPLUS dataset component in Delphi XE4. Just use Insert and Edit procedures for this purpose. First of all create a dataset of type TpFIBDataset. Lets have a look at this very simple example.

var
dsMyFirebirdDataset : TpFIBDataset;

Insert a row in a dataset

with dsMyFirebirdDataset do
begin
Insert;
dsMyFirebirdDatasetID.AsInteger := 101;
dsMyFirebirdDatasetDESC.AsString := 'Hello';
Post;
end;

You can also use FieldByName like following:

with dsMyFirebirdDataset do
begin
Insert;
FieldByName('ID').AsInteger := 101;
FieldByName('DESC').AsString := 'Hello';
Post;
end;

Similarly, you can edit a record/row in the dataset like following:

Edit a row in a dataset

With dsMyFirebirdDataset do
begin
Edit;
dsHdwPriceGroupDESC.AsString := 'Hello World';
Post;
end;

or

With dsMyFirebirdDataset do
begin
Edit;
FieldByName('DESC').AsString := 'Hello World';
Post;
end;

Friday, May 9, 2014

How to populate data into dataset from Firebird database in Delphi using FIBPLUS components?

How to populate data into dataset from Firebird database in Delphi using FIBPLUS components?

I am using Firebird 2.5.2 database and Delphi XE4. I will be using FIBPlus TpFIBDatabase and TpFIBDataset components to populate data from Firebird database to dataset in Delphi XE4. For this, you have to drag TpFIBDatabase and TpFIBDataset components into your Delphi Form from the Tool Palette. Set various properties of TpFIBDatabase component like DBName, Username, Password and LibraryName to connect to Firebird database. I have written a complete tutorial on this. After successfully creating the database connection, set following properties of TpFIBDataset component:

Database: Provide the name of database component (TpFIBDatabase) in Database property. In my case, I have created dbMyDatabase component in my previous article.

SQLs: Write the query which you want to run. In my case, I am running following query:

SELECT ID, NAME FROM MY_FIREBIRD_TABLE WHERE ID = :ID AND NAME = :NAME;

Now, populate your dataset like this:

var
dsMyDataSet : TpFIBDataSet;

with dsMyDataSet do
begin
  Active := False;
  Params.ParamByName('ID').AsInteger := 1000;
  Params.ParamByName('NAME').AsString := 'Naresh';
  Active := True;
  RecordCount;
end;

Note: You can also set Database and SQLs properties in pas file as following:

with dsMyDataSet do
begin
  Active := False;
  Database := dbMyDatabase;
  SQLs.SelectSQL.Text := 'SELECT ID, NAME FROM MY_FIREBIRD_TABLE WHERE ID =:ID                                               AND NAME = :NAME;';
  Params.ParamByName('ID').AsInteger := 1000;
  Params.ParamByName('NAME').AsString := 'Naresh';
  Active := True;
  RecordCount;
end;

How to create database connection with Firebird in Delphi using FIBPLUS components?

How to create database connection with Firebird in Delphi using FIBPLUS components?

I am using Firebird 2.5.2 with Delphi XE4. I will show you how to create a database connection with Firebird database in Delphi XE4 using FIBPLUS component? Just go into the Tool Palette and search for TpFIBDatabase component under FIBPLUS. Drag it into the form and name it. I have given "dbMyDatabase" name to TpFIBDatabase database component. If you see your pas file, a declaration for TpFIBDatabase will look like this:

var
dbMyDatabase: TpFIBDatabase;

Now create a function "ConnectToDatabae" with return type boolean. This function will return true if Firebird database connection is established successfully otherwise false.

function TMyForm.ConnectToDatabase : boolean; 
begin
  result := False;
  try
    try
      with dbMyDatabase do
     begin
        DBName := 'C:\MyProject\MyDB.FDB';
ConnectParams.UserName := 'SYSDBA';
ConnectParams.Password := 'masterkey';
LibraryName := 'C:\Program Files(86)\Firebird\Firebird_2_5\bin\fbclient.dll'; 
Connected := True;
     end;
     result := True;
    except
`     result := False;
end;
  finally
    dbMyDatabase.Connected := False;
  end;
end;

In the above function, I have set different properties of TpFIBDatabase component like DBName, Username, Password, LibraryName etc as following:

DBName := 'C:\MyProject\MyDB.FDB'; //MyDB is the firebird database name
ConnectParams.UserName := 'SYSDBA'; //Default username of firebird database
ConnectParams.Password := 'masterkey'; //Default password of firebird database
LibraryName := 'C:\Program Files(86)\Firebird\Firebird_2_5\bin\fbclient.dll'; //Default library path of firebird database

Note: You can set all these properties at design time in your dfm file. But I would recommend to write all these settings in your pas file.

After setting the above properties, I have set connected property to true. If Firebird database connection is established successfully, above function will return true otherwise false. Finally, I am disconnecting the database.

Tuesday, March 11, 2014

How to use Generic TList Class in Delphi?

How to use Generic TList Class in Delphi?

TList generic class is used to store a list of various data type variables in Delphi. Below is the simple program to illustrate the concept of TList generic class in Delphi.

var
  List: TList<Integer>;
  FoundIndex: Integer;

begin
  { Create a new List. }
  List := TList<Integer>.Create;
  { Add a few values to the list. }
  List.AddRange([5, 1, 8, 2, 9, 14, 4, 5, 1]);

  writeln('Index of first 1 is ' + IntToStr(List.IndexOf(1)));
  writeln('Index of last 1 is ' + IntToStr(List.LastIndexOf(1)));
  writeln('Does List contains element 100? ' + BoolToStr(List.Contains(100)));

  { Add another element to the list. }
  List.Add(100);

  writeln('There are ' + IntToStr(List.Count) + ' elements in the list.');

  { Remove the first occurrence of 1. }
  List.Remove(1);
  { Delete a few elements from position 0. }
  List.Delete(0);
  List.DeleteRange(0, 2);
  { Extract the remaining 1 from the list. }
  List.Extract(1);
  { Set the capacity to the actual length. }
  List.TrimExcess;
  writeln('Capacity of the list is ' + IntToStr(List.Capacity));

  { Clear the list. }
  List.Clear;
  { Insert some elements. }
  List.Insert(0, 2);
  List.Insert(1, 1);
  List.InsertRange(0, [6, 3, 8, 10, 11]);

  { Sort the list. }
  List.Sort;

  { Binary search for the required element. }
  if List.BinarySearch(6, FoundIndex) then
    writeln('Found element 6 at index ' + IntToStr(FoundIndex));

  { Reverse the list. }
  List.Reverse;
  writeln('The element on position 0 is ' + IntToStr(List.Items[0]));
  List.Free;
  readln;

end.