FireDac transaction behaving strangely - delphi

I'm using Firedac to connect to a Firebird 2.1 database in Delphi 10.1 Berlin. A TFDConnection has a TFDtransaction assigned. Both with default values. Then there's a code like that, more or less.
TFDtransaction.StartTransaction;
try
.. // Select, update & insert statements in TFDQuery components created dinamically here with default values
TFDtransaction.Commit;
except
TFDtransaction.Rollback;
end;
The problem is, sometimes (not always), when checking the values changed by this transaction (in FlameRobin, for example) I can't see the new values until I close the application (that is closing the connection too). Why is that so? How I can solve this? Is there a problem in the update options in the TFDConnection component?

Related

FireDAC (FDQuery) - database with dot in it's name

I have got this problem with FireDAC -> FDQuery component when it tries to select data from a database with '.' (dot) in its name.
The database name is TEST_2.0 and the error on Opening the dataset says:
Could not find server 'TEST_2' in sys.servers [...]
I have tried {TEST_2.0} (curly brackets) and [TEST_2.0] (square brackets). Also setting QuotedIdentifiers (Format Opetions) property to True does not seem to fix the problem. In SQL query I can add 'SET QUOTED_IDENTIFIER ON;' but this breaks inserts to the dataset.
The FDConnection component can connect to that server and that database using MSSQL driver without problems. It seems it is the dataset that dosn't handle it. UniDAC seems to handle everything without any problems.
I am using RadStudio 10.2.
Has anyone found any solution to this? Thanks in advance for any replies
I got a response from Emarcadero and it works for me:
"The problem is not in FireDAC, but in SQL Server ODBC driver
SQLPrimaryKeys function. It fails to work with a catalog name
containing a dot. FireDAC uses this function to get primary key fields
for a result set, when fiMeta is included into FetchOptions.Items. So,
as a workaround / solution, please exclude fiMeta from
FetchOptions.Items."
What is wrong?
I was able to reproduce what you've described here. I've ended up on metainformation command, specifically the SQLPrimaryKeys ODBC function call. I have used SQL Server Native Client 11.0 driver connected to Microsoft SQL Server Express 12.0.2000.8, local database server instance.
When I tried to execute the following SQL command (with TEST_2.0 database created) through a TFDQuery component instance with default settings (linked connection object was left with empty database connection parameter) in Delphi Tokyo application:
SELECT * FROM [TEST_2.0].INFORMATION_SCHEMA.TABLES
I got this exception raised when the SQLPrimaryKeys function was called with the CatalogName parameter set to TEST_2.0 (from within the metainformation statement method Execute):
[FireDAC][Phys][ODBC][Microsoft][SQL Server Native Client 11.0][SQL
Server]Could not find server 'TEST_2' in sys.servers. Verify that the
correct server name was specified. If necessary, execute the stored
procedure sp_addlinkedserver to add the server to sys.servers.'.
My next attempt was naturally modifying that CatalogName parameter value to [TEST_2.0] whilst debugging, but even that failed with similar reason (just failed for the name [TEST_2), so for me it seems that the SQLPrimaryKeys ODBC function implementation with the driver I've used cannot properly handle dotted CatalogName parameter values (it seems to ignore everything after dot).
What can I do?
The only solution seems to be just fixing ODBC drivers. Workaround I would suggest is not using dots in database names (as discussed e.g. in this thread). Another might be preventing FireDAC from getting dataset object metadata (by excluding fiMeta option from the Items option set). That will bring you the responsability of supplying dataset object metadata by yourself (at this time only primary key definition).

Server opens Stored Procedure like Unicode

As you can see in the image bellow, my SQL Stored Procedures, somehow, my SQL Server opens Procedures like Unicode SPs.
That was not the case before, and I have no idea how this apeared now.
I have around 5.000 stored procedures so there is no chance I can edit it manualy.
My SPs starts from ALTER PROCEDURE , everything before that is somehow added.
Your SP's will still work just fine. This is just the way SQL Server Management Studio scripts the objects when you want to generate ALTER- or CREATE-statements.
To change this behavior, go to Tools > Options > SQL Server Object Explorer > Scripting
Set the option "Include IF NOT EXISTS clause" to "False".
(In other versions of SQL Server Management Studio the option might be called something like "Check for object existence")
As previously answered, changing the scripting option "Include IF NOT EXISTS clause" to false solves the problem. To add context, if this value is true, it has to be scripted by putting the entire Alter Procedure statement in an #statement variable, because the conditional logic associated with the check for existence requires the ALTER PROCEDURE statement be inside a BEGIN/END block, which is not allowed. So Microsoft's workaround is to put the entire ALTER PROCEDURE statement in the #statement variable, which is executed conditionally inside a BEGIN/END block.

Delphi IBTable readonly error

I just installed the latest version of Embarcadero Delphi XE3. I made a simple form connecting to InterBase Database. I have IBDatabase, IBTable, IBTransaction, Grid and some other components. Everything works fine and it shows data in the grid. But I want to be able to edit this data. So at the IBTable component I set the ReadOnly property to false and every time I do this the program stops working and I get this:
Dynamic SQL Error
SQL error code = - 206
Column unknown
IBTable1
Any idea how to solve this?
It is not recommended to use IBTable component. Usage of IBDataset or IBQuery is advised. Read this

Do ADO components, especially TADOCommand, work more reliably with un-named, or named parameters, in some cases?

There are several questions on StackOverflow that seem to have answers that contradict each other on the subject of ADO/OleDB, delphi TADOQuery/TADOCommand and the subject of parameters.
Parameters can be introduced two ways, in the CommandText or SQL property of an ADO component. Named parameters, which work most of the time for me, are introduced with colons:
select a, b, c from bar where bat = :baz
This works, 99% of the time for me, just fine. Every now and then I find that ADO or Delphi's wrappers around it, won't accept ":baz" and requires that I write this instead:
select f, g, h from bar where bat = ?
This results in an unnamed parameter, instead of a named parameter. When an ADO Query or ADO Command contains only one parameter, this isn't a big deal. But that's not when ADO acts up on me. Yesterday it acted one way, and today, a different way with a dual-command in a single TADOCommand object, like this, with two commands in one CommandText string:
delete from bar where id = :id1
delete from bat where id = :id2
I had to change it to this:
delete from bar where id = ?
delete from bat where id = ?
It worked all day yesterday. Today, I had to change it back to the first version, to get it to work. The symptom was that the ADO parameters disappeared and would not come back, and when I try to execute the command I get an error, index out of range, when I try to access Parameters[0]. Nothing gives me any warning that the parameters are going away. It seems that a few connections to the ADO dataset, at designtime, jogs the TADOCommand component, in particular, and it "just breaks on me". It is particularly maddening when you're trying to write a query or a command, and you know it works, but the ADO component has decided not to accept "?" or ":x" right now. You can get around its total inability to function by switching from one to the other. But it frustrates me, and probably actually completely blocks other people. I know some people always dynamically build their SQL in code, and avoid using Parameters, and maybe this is why.
Possible answers to my question that I'm anticipating are:
ADO doesn't support multiple commands, or at least Delphi's wrappers don't. Or maybe TADOCommand just doesn't work reliably here.
Parameters are a buggy area in all of ADO, or all of Delphi's ADO wrappers?
You're doing it wrong.
I'm using Delphi XE2, but I've seen similarly dodgy behaviour in 2007, 2009, 2010, and XE.
I'm using Microsoft OLEDB Provider for SQL Server as my OLEDB Provider.
Named parameters with :? I always used it with #, even on Visual Studio (ADO.NET).
And in T-SQL parameters and variable are prefixed with #.
Do not remember having problems with that... Are you sure you doesn't choose Native Client
(installed with an SQL server client install) instead of OLEDB Provider for SQL Server (which
comes with Windows)?
Unfortunately, I've not used Delphi in awhile, so, and I don't have the means to validate this answer from the Delphi perspective.
This is the first time I've seen named parameters prefixed with a colon (:). Usually, in ADODB, the named parameters are prefixed with an at (#) and, yes, unnamed parameters are given with a question mark (?).
One significant advantage of named parameters is their ability to be reused, i.e.
INSERT INTO TABLE T VALUES (#id, #id, 'Hello World');
At the ADODB level. Once you used parameters, either named, or unnamed, you can use CommandText.Parameters.Refresh as a fast means of creating the parameters.
Yes there are some cases where parameters with ? fail. I have found sometimes I need to use :named parameters. Named parameters have an advantage for working with the DB Parameter values, since having the Name property set makes debugging the ADO query or dataset or table easier as well.
I do not understand why. If you have this problem, first check you are using the correct OLEDB provider, and check what version. Also check for potential parsing errors caused by bad SQL generated by you.
I suspect that an internal behaviour inside the OLEDB provider in code that I do not have source code for is to blame for this quirk. The Delphi ADO class wrappers are translators from Delphi's database component layer architecture to ADO's core query/table/dataset APIs all of which are under the hood wrappers around a set of COM objects that deal with ADO RecordSets.

How to read and write dbf in a native way?

In Delphi for Win32, how to read and write a dbf file in a native way, without the BDE? I know there are some components available in the web, but I have never used any of them, so I don't know which to choose (if any).
You can use ADO to access a DBF File
See ths sample code (using an TAdoConnection and TAdoDataSet components).
var
dbf_folder : string;
begin
dbf_folder:='c:\bdd';//set your dbf folder location here
ADOConnection1.LoginPrompt:=false;
ADOConnection1.ConnectionString:=Format('Provider=Microsoft.JET.OLEDB.4.0;Data Source=%s;Extended Properties=dBase IV;',[dbf_folder]);
try
ADOConnection1.Connected:=True;
ADODataSet1.CommandText:='Select * from file.dbf'; //make your SQL query using the name of the dbf file
ADODataSet1.Open;
while not ADODataSet1.eof do
begin
//do your stuff here
//ADODataSet1.FieldByName('').AsString
ADODataSet1.Next;
end;
except
on E : Exception do
ShowMessage(E.Message);
end;
end;
I used TDBF back when I was still working with DBF files (some legacy apps). I still use it for maintainance of those apps here and there. It is free, has a lot of features and works good.
I used Topaz from Software Science for many years before I got started with Firebird. It was always an excellent library, had a terrific manual and good technical support. It supports indexes and even has an in-memory option. I think it would be a good choice.
Apollo Database VCL.
ADO didn't work for me but I managed to open my dbf file using BDE:
From a Data Access (or BDE, depends on your version of Delphi) section I put a TDataBase and, TTable components (you can use TQuery if you want).
By doubleclick on TDataBase component I opened the setup dialog. Filled the Name field with 'db_name' (the name is arbitrary), driver name = 'STANDARD', Parameters field: 'PATH=C:\Path\To\DBF_FILES\'.
Then I set Connected=True.
Then in TTable component I set DatabaseName = 'db_name' - the one I set in TDataBase component. And TableName property set 'DB_FILE.dbf' which was located in the specified folder.
Active = True.
You know what to do next
It is not hard to read a DBF file if you don't need indexes. The format is pretty straightforward. A header followed for fixed sized registers. There is a flag in each register which indicates if it is deleted or not. I suggest looking for a component which does what you want. You can find some in Torry's Delphi pages.

Resources