I've build a dataset in Delphi in which I have a ADOQuery that selectes 2 colums from a table... I drag and dropped a column from that ADOQuery into a form, how can I Acces my values from that column. I want to put that values into the combobox.
unit SCArabica;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, Mask, DBCtrls, Grids, DBGrids;
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
DBGrid1: TDBGrid;
Label9: TLabel;
DBEdit1: TDBEdit;
DataSource1: TDataSource;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
published
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
end.
DATASET Code
unit SCArabicaDataSet;
interface
uses
SysUtils, Classes, FMTBcd, DB, SqlExpr, ADODB;
type
TDataModule1 = class(TDataModule)
ad: TADOConnection;
ADOQuery1: TADOQuery;
ADOQuery1CategoriePermisID: TIntegerField;
ADOQuery1Categorie: TWideStringField;
private
{ Private declarations }
public
{ Public declarations }
end;
var
DataModule1: TDataModule1;
implementation
{$R *.dfm}
end.
I'm new with Delphi can you guide me to some tutorials on how to build a program in Delphi that acces databases?
In my opinion, a good design would be to add a method in TDataModule1 to fetch records from the dataset and fill a TStrings. Then from the main code, you simply pass combobox.items.
procedure TDataModule1.FetchRecords(OutStrings : TStrings);
begin
ADOQuery1.SQL.Text := 'SELECT COMPANY FROm COMPANIES WHERE COUNTRY="BELGIUM"';
ADOQuery1.Open;
while not ADOQuery1.Eof do begin
OutStrings.Add(ADOQuery1.Fields[0].AsString;
ADOQuery1.Next;
end;
end;
Then you can write code in the form:
ComboBox1.Items.Clear;
DataModule1.FetchRecords(ComboBox1.Items);
I just typed this out of my head, so maybe some minor error, but you get the idea...
while not dm1.ADOQuery2.Eof do
begin
DBComboBox1.Items.Add(dm1.ADOQuery2.Recordset.Fields['IDMasina'].Value) ;
dm1.ADOQuery2.Next;
end;
This is my solution.
dm1 is a DataSource
ADOQuery2 is a DataSet
Related
hi i dont know if i asked the question clearly.
i have a deferred class "animal" which contains two features : "bite" (this returns a boolean -> bite:BOOLEAN) and "speak"(speak(word:BOOLEAN)).
now i made a class named "dog" what inherit from "animal". i redefined the two features without a compiler error. now i want to make a create, which contains the function bite (create bite:BOOLEAN).
this gaves me a compiler error, if i try it with the other feature it works fine.
my error code : VGCP(2) creators part lists improper identifier.
thank u for ur help
My Application.e:
note
description : "root class of the application"
date : "$Date$"
revision : "$Revision$"
class
APPLICATION
inherit
ARGUMENTS_32
create
make
feature
d1:DOG
feature {NONE} -- Initialization
make
-- Run application.
do
print(d1.bite)
print ("Hello Eiffel World!%N")
end
end
my animal class:
deferred class
ANIMAL
feature
bite_:BOOLEAN
deferred
end
feature
speak(word:BOOLEAN)
deferred
end
end
my dog class:
class
DOG
inherit
ANIMAL
redefine
bite_,speak_
end
create
bite_
feature
bite_:BOOLEAN
do
Result:=5<3
end
feature
speak(word:BOOLEAN)
do
print("yes")
end
I'm not sure what is the intended semantics of feature speak, so I'll focus solely on feature bite, or, to express the supposed intention better can_bite. Class ANIMAL is similar to what you have:
deferred class
ANIMAL
feature -- Status report
can_bite: BOOLEAN
-- Can this animal bite?
deferred
end
end
With class DOG, two variations are possible: when every dog bites (possibly, depending on some internal state), when the ability to bite is set at object creation time.
In the first scenario, can_bite is a function and the class looks like
class
DOG
inherit
ANIMAL
feature -- Status report
can_bite: BOOLEAN
-- Can this animal bite?
do
Result := True -- It could also be some expression.
end
end
In the second scenario, can_bite is an attribute initialized by a creation procedure, and the class looks like
class
DOG
inherit
ANIMAL
create
make
feature {NONE} -- Creation
make (is_biting: BOOLEAN)
-- Initialize with ability `is_biting`.
do
can_bite := is_biting
end
feature -- Status report
can_bite: BOOLEAN
-- Can this animal bite?
end
Note that in both cases the client has to create the dog object before making any calls on it. In the first case, the default creation procedure is used, and the client code looks like
create d1
print (d1.can_bite)
In the second case, the specific creation procedure is used (it initializes can_bite), and the client code looks like
create d1.make (True)
print (d1.can_bite)
When we swapped database components from ODBC Express to ADO one of the biggest problems we ran into was that ODBC Express "right-trimmed" the results from CHAR fields and ADO didn't.
CHAR fields fill up their entire assigned field length so when we query them with ADO you get a lot of extra spaces.
We have a lot of databases and code that basically depends on the results from the database being trimmed.
Our solution was to edit the delphi source DB.pas and change the getasstring methods from TField and TStringField.
This works but is not a solid solution is there another way to get those results trimmed without changing delphi source code?
When switchting to ADO we decided to not use the TADOQuery class directly but instead we derived our own:
TOurAdoQuery = class(TADOQuery)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function ExecSQL: Integer;
procedure Open;
end;
Descend from TStringField, something like:
TYourStringField = class(TStringField)
protected
function GetAsString: string; override;
end;
implementation
function TYourStringField.GetAsString: string;
begin
Result := TrimRight(inherited GetAsString);
end;
Register your class (you will probably do this in initialization section):
RegisterClass(TYourStringField);
Put this line where you usually initialize stuff for your application :
DefaultFieldClasses[ftString] := TYourStringField;
That's it, next time you create dataset all ftString field types will use TYourStringField definition.
When I want to confirm a form exit, I use a DialogMsg call with an if to set Action parameter to caNone (No) or caHide (yes).
When I use that approach with database table row posting, I get a problem.
If I make a Save button with a confirmation dialog, I could call Post or Cancel, but when I have a Database Grid in the form, the problem comes when the user alter a row and later, selects another row, witch saves the previous row automatically.
The solution I found was to put the save confirmation dialog inside the OnBeforePost, but if the uses says No, how should I cancel the Post command to Continue? I've tryed Cancel and Abort commands, but it continues saving the row.
You need to create your own descendant TMyQuery of the TXxxQuery (or what else dataset kind you are using). And in your class override Post method and add a new event, allowing to decide is the Post needed. Then register new component and replace TXxxQuery in your application with TMyQuery. And create the event handler.
For example, the TMyQuery:
interface
type
TMyAllowPostEvent = procedure (ASender: TDataSet; var AAllow: Boolean) of object;
TMyQuery = class (TXxxQuery)
private
FOnAllowPost: TMyAllowPostEvent;
public
procedure Post; override;
published
property OnAllowPost: TMyAllowPostEvent read FOnAllowPost write FOnAllowPost;
end;
implementation
procedure TMyQuery.Post;
var
lAllow: Boolean;
begin
lAllow := True;
if Assigned(OnAllowPost) then
OnAllowPost(Self, lAllow);
if lAllow then
inherited Post;
end;
And the example of the event handler:
procedure TForm1.MyQuery1AllowPost(ASender: TDataSet; var AAllow: Boolean);
begin
AAllow := MessageDlg('Would you like to save changes ?', mtConfirmation, mbYesNo, -1) = mrYes;
end;
This is my whole code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Images: array[0..29,0..39] of TImage; //array
implementation
{$R *.dfm}
//form create
procedure TForm1.FormCreate(Sender: TObject);
var xx,yy: Integer; //local variables
begin
for xx:=0 to 29 do
for yy:=0 to 39 do
begin
Images[xx,yy]:=Timage.Create(Form1);
Images[xx,yy].Canvas.Rectangle(0,0,17,17);
Images[xx,yy].Left:=xx*16;
Images[xx,yy].Top:=yy*16;
end;
end;
end.
And I always get the error : "Project Project1.exe has raised the exception class EClassNotFound with message "TImage not found". Process stopped. Use step or run to continue "
I have tried other codes on the internet like:
Delphi: TImage.Create causes Access violation http://www.delphi-central.com/tutorials/memory_game_2.aspx
Nothing helps! Why is this happening?
Thank you.
Are you sure you get the exception at the line with TImage.Create? Could it be you have an invalid DFM file still containig a TImage instance which is missing from the TForm1 declaration?
Normally all classes used as children in a form or datamodule are automatically registered for streaming. As there is no TImage declared in the form and no other form of the application contains a TImage, there is no registration.
You can simply test by dropping a TImage onto the form.
and if you want to show in form add this code to loop:
Images[xx,yy].Parent:= Self;
Some Background
I have a game database with a table called Games that has multiple attributes and one called Genres. The Genres attribute is defined as an integer[] in PostgreSQL. For the sake of simplicity, I'm not using any foreign key constraints, but essentially each integer in this array is a foreign key constraint on the id attribute in the Genres table. First time working with the NetBeans Master/Detail Sample Form and Java persistence and it's been working great so far except for 1 thing. I get this error when the program tries to display a column that has a 1-dimensional integer array. In this example, the value is {1, 11}.
Exception Description: The object [{1,11}], of class [class org.postgresql.jdbc3.Jdbc3Array], from mapping [oracle.toplink.essentials.mappings.DirectToFieldMapping[genres-->final.public.games.genres]] with descriptor [RelationalDescriptor(finalproject.Games --> [DatabaseTable(final.public.games)])], could not be converted to [class [B].
Exception [TOPLINK-3002] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ConversionException
My Research
From what I've been able to read, it looks like PostgreSQL arrays need something special done to them before you can display and edit them in this template. By default, the sample form uses TopLink Essentials (JPA 1.0) as its persistence library, but I can also use Hibernate (JPA 1.0).
Here is the code that needs to be changed in some way. From the Games.java file:
#Entity
#Table(name = "games", catalog = "final", schema = "public")
#NamedQueries({
// omitting named queries
#NamedQuery(name = "Games.findByGenres", query = "SELECT g FROM Games g WHERE g.genres = :genres")
})
public class Games implements Serializable {
#Transient
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
private static final long serialVersionUID = 1L;
// omitting other attributes
#Column(name = "genres")
private Serializable genres;
// omitting constructors and other getters/setters
public Serializable getGenres() {
return genres;
}
public void setGenres(Serializable genres) {
Serializable oldGenres = this.genres;
this.genres = genres;
changeSupport.firePropertyChange("genres", oldGenres, genres);
}
} // end class Games
Here are also some of the sites that might have the solution that I'm just not understanding:
https://forum.hibernate.org/viewtopic.php?t=946973
http://blog.xebia.com/2009/11/09/understanding-and-writing-hibernate-user-types/
// omitted hyperlink due to user restriction
Attempted Solutions
I'm able to get the data to display if I change the type of genres to String, but it is immutable and I cannot edit it. This is what I changed to do this:
#Column(name = "genres")
private String genres;
public String getGenres() {
return genres;
}
public void setGenres(String genres) {
String oldGenres = this.genres;
this.genres = genres;
changeSupport.firePropertyChange("genres", oldGenres, genres);
}
I also attempted to create a UserType file for use with Hibernate (JPA 1.0), but had no idea what was going wrong there.
I also attempted to use the #OneToMany and other tags, but these aren't working probably because I'm not using them properly.
What I'm Looking For
There has to be a simple way to get this data to display and make it editable, but since I'm completely new to persistence, I have no idea what to do.
The effort put into your question shows. Unfortunately JPA does not currently support PostgreSQL arrays. The fundamental problem is that arrays are not frequently used in many other databases frequently and so heavy reliance on them is somewhat PostgreSQL specific. Thus you can expect that general cross-db persistence API's are not generally going to support them well if at all. JPA is no exception, having currently no support for PostgreSQL arrays.
I have been looking at writing my own persistence API in Java that would support arrays, but it hasn't happened yet, would be PostgreSQL-only when written, and would be based on a very different principle than JPA and friends.