Error using TADODataset component with MS Access - delphi

I am attempting to replace a InterBase DB with a MS Access DB as a test, I am connect to the MS Access DB using the TADOConnection component successfully; however when I try to connect to a table using the TADODataset, I am able to set the Connection property to the TADOConnection component but when I want to set the CommandText property I receive the following error:
The connectionstring is as follows: Provider=ADsDSOObject;User ID=admin;Encrypt Password=False;Data Source=C:\StudyTime\StudyTime.accdb;Mode=Read;Bind Flags=0;ADSI Flag=-2147483648;
Can someone please assist me?

You are using a wrong provider: ADsDSOObject for ms-access.
Use Provider=Microsoft.Jet.OLEDB.4.0 or Provider=Microsoft.ACE.OLEDB.12.0; instead.
e.g.
MdbFileName := 'C:\StudyTime\StudyTime.accdb';
ADOConnection1.ConnectionString := Format('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s;', [MdbFileName]);
ADOConnection1.Open;

Related

Is this a bug: stored procedure runs fine without parameters, causes error when parameters are added?

I have a stored procedure created in MySQL DB. This database is accessed as linked server through Microsoft SQL Server 2012 using Microsoft SQL Server Management Studio. The provider selected while creating linked server is "Microsoft OLE DB Provider for ODBC Drivers".
When I run following as text from Report builder 3.0 it runs fine and fetch data.
EXEC('CALL storedProcedureName(''string1'', ''string2'', ''string3'')') AT LinkedServerName;
But when I try to replace string1, string2, string3 with parameter name parameter1, parameter2, parameter3 as:
EXEC('CALL storedProcedureName(#parameter1, #parameter2, #parameter3)') AT LinkedServerName;
I get error:
Could not execute statement on remote server 'LinkedServerName'.
(Microsoft SQL Server, Error: 7215)
And when I try:
EXEC('CALL storedProcedureName('#parameter1', '#parameter2', '#parameter3')') AT LinkedServerName;
I get the prompt to enter values for parameter1, parameter2, parameter3. But when I enter the values and click ok, I get error:
Incorrect syntax near '#parameter1'. (Microsoft SQL Server, Error: 102)
Question: Am I missing something in syntax or is this a bug?
The linked server has:
"RPC" and "RPC out" set to True.
And the OLEDB provider has:
Enabled allow inprocess
Enabled dynamic parameter
I believe you have to call it like the below. So params become strings wrapped in single quotes:
EXEC('CALL storedProcedureName('''+#parameter1+''', '''+#parameter2+''', '''+#parameter3+''')') AT LinkedServerName;
I know this is an older question but the accepted answer is open to SQL Injection and I think it's important to offer a more secure method.
You really want to use a parameterized query
EXEC('CALL storedProcedureName(?,?,?)',#parameter1, #parameter2, #parameter3) AT LinkedServerName;
I know this works for oracle and it should work for MySql as well.

Delphi XE3 - Does Reuse socket rsTrue get overridden by system in any case?

Recently I made some very small, very light app that uses two UDP client and two UDP Server components. Apart from several functions, it has basically nothing else in it.
I was stuck for a while with "Cannot bind socket. Address and port already in use", but somehow solved that with changing the ports, using rsTrue property on Reuse Socket, but somehow, several users still got that error when they try to run the connection from the app.
The server and client has to use same port and same address, as the UDPClient needs to have BoundPort the same as UDPServer's binding port. That's because the responses are being sent to the same port the request came from. This was causing the primary error, which was solved with rsTrue property.
Now I wonder, is there any chance that system overrides this settings by something, I'm not familiar with? Because on 12 computers I have tested so far, it worked fine (on one I had to kill Bonjour service as it was using the exact port that I needed, but other than that...)
What could be causing errors otherwise?
These are settings which are being called on Connect button click:
Server.Binding.IP:=Interface.Text;
Server.Binding.Port:=StrToInt(Port.Text);
Server.DefaultPort:=StrToInt(Port.Text);
Client.Host:= DeviceIP.Text;
Client.Port:= 10023;
Client.BoundIP:= Interface.Text;
Client.BoundPort:= StrToInt(Port.Text);
LocalServer.Binding.IP:= '127.0.0.5';
LocalServer.Binding.Port:= 10023;
LocalServer.DefaultPort:= 10023;
LocalClient.BoundIP:= '127.0.0.1';
LocalClient.BoundPort:= 10024;
LocalClient.Host:= '127.0.0.1';
LocalClient.Port:= 10023;
try Client.Active:=True; finally end;
try Server.Active:=True; finally end;
try LocalClient.Active:=True; finally end;
try LocalServer.Active:=True; finally end;
Where Port is the TEdit field for user to enter port, DeviceIP the device's IP, and Interface the local network interface IP that he will use.
The only hardcoded thing that doesn't really need to be hardcoded is LocalClient.BoundPort:=10024, it's just to make GUI as light as possible. But changing this doesn't help either.
The app is kind of a proxy server between the original App on PC, and the device on network.
The 10023 must be set as is, since the device only listens on that port, and the original app only sends to that port!
Any help would be appreciated.
You do not need to use separate TIdUDPClient and TIdUDPServer on the same port. You can use TIdUDPServer by itself and let it handle both sending and receiving. No need to use a separate TIdUDPClient at all.
Also, you are not using the Binding property correctly. When you read a server's Binding property for the first time, the socket is bound using the settings from the server's Bindings collection. Your assignments to Binding.IP and Binding.Port are then ignored. You need to configure the server's Bindings collection first, then use the server's Binding property only for sending (the server will handle the reading for you).
Try this:
Server.Active := False;
Server.Bindings.Clear;
Server.DefaultPort := StrToInt(Port.Text);
Server.Bindings.Add.IP := Interface.Text;
Server.Active := True;
...
Server.Binding.Send(DeviceIP.Text, 10023, data here);
Replies will arrive in the server's OnUDPRead event.
BTW, since you are writing a proxy, have a look at the TIdMappedPortUDP component.

Creating a database in Firebird using FireDac (Delphi)

I recently changed from AnyDac to FireDac (8.0.5.3365). We're running Delphi 2006.
When I was using the AnyDac version of this component I could create a new database by doing the following..
Setup my connection
fConnection.LoginPrompt := false;
fConnection.ResourceOptions.SilentMode := true;
fConnection.Params.Clear;
fConnection.Params.Add(Format('DriverID=%s', ['IB']));
fConnection.Params.Add(Format('Database=%s', [fConnectionInfo.xDatabase]));
fConnection.Params.Add(Format('CharacterSet=%s', ['UTF8']));
fConnection.Params.Add(Format('user_name=%s', [fConnectionInfo.xUserName]));
fConnection.Params.Add(Format('password=%s', [fConnectionInfo.xPassword]));
fConnection.Params.Add(Format('ExtendedMetadata=%s', ['True']));
fConnection.Params.Add(Format('CreateDatabase=%s', ['Yes']));
fConnection.Params.Add(Format('Protocol=%s', ['Local']))
//database path = C:\Users\LoginName\AppData\Local\AppName\TestDB.FDB
Open and close the connection
fConnection.Open;
fConnection.Close;
And then I could run my create table sql scripts on the existing database.
But now when I do this with the FireDac version, the Open command raises the fbe_unavailable error as if I didn't specify the CreateDatabase parameter.
Should I be doing this a different way?
Thanks for your time.
Corey.
You have a full example here http://docwiki.embarcadero.com/RADStudio/Rio/en/Executing_SQL_Scripts_%28FireDAC%29
For example, the following Firebird script creates a database, and can be executed using TFDScript:
SET SQL DIALECT 3;
SET NAMES UTF8;
SET CLIENTLIB 'C:\fb25\bin\fbclient.dll';
CREATE DATABASE 'E:\Test2.ib'
USER 'sysdba' PASSWORD 'masterkey'
PAGE_SIZE 16384
DEFAULT CHARACTER SET NONE;
SET TERM ^ ;
CREATE PROCEDURE MY_PROC RETURNS (aParam INTEGER) AS
BEGIN
aParam = 10;
END^
You should use CreateDatabase=Yes connection definition parameter
additionally to other required parameters:
http://docwiki.embarcadero.com/RADStudio/Rio/en/Connect_to_Firebird_(FireDAC)

Delphi TClientDataSet "Trying to modify read-only field" error in SQL Server 2008, OK in 2000

Embarcadero® Delphi® 2010 Version 14.0.3593.25826
We are attempting to move a database from SQL Server 2000 to SQL Server 2008. I have a TClientDataSet that is loaded with a SELECT that includes a computed column, i.e., "SELECT Comp_Col = Column1 + ' ' + Column2...".
Running against an SQL Server 2000 database, I can modify the value of the column in the TClientDataSet using the following code:
ClientDataSet1.Edit();
ClientDataSet1.FieldByName('Comp_Col').ReadOnly := false;
ClientDataSet1.FieldByName('Comp_Col').Value := 'MODIFIED';
ClientDataSet1.FieldByName('Comp_Col'').ReadOnly := true;
ClientDataSet1.Post(); // <-- EXCEPTION in 2008
Running against an SQL Server 2008 database, though, I get a "Trying to modify read-only field" error when executing .Post().
I have tried also setting .ProviderFlags = '[]' for the column (in addition to .ReadOnly = false) in the above code, but still get the error. I have also tried setting .ReadOnly = false and .ProviderFlags = '[]' at design-time via the IDE, but this does not help either.
Anybody know how to set a computed column in a TClientDataSet when running against an SQL Server 2008 database?
Thanks!
* UPDATE: ANSWERED *
I discovered the problem--or at least a workaround...
I WAS setting .ReadOnly = false for the column in the TClientDataSet object. This worked with SQL Server 2000 but not with SQL Server 2008.
If I set .ReadOnly = false in for the column instead in the TADOQuery object that is serving as the provider, then I am able to set the value of the computed column in the TClientDataSet object at run-time.
Not ideal for me since this was implemented in a generic function for TClientDataSet objects (that didn't anything about the provider), but it will have to do for now.
I discovered the problem--or at least a workaround . . .
I WAS setting .ReadOnly = false for the column in the TClientDataSet object. This worked with SQL Server 2000 but not with SQL Server 2008.
If I set .ReadOnly = false for the column instead in the TADOQuery object that is serving as the provider, then I am able to set the value of the computed column in the TClientDataSet object at run-time.
Not ideal for me since this was implemented in a generic function for TClientDataSet objects (that didn't anything about the provider), but it will have to do for now.
My experience shows that the creation of ClientDataSet fields by calling TClientDataSet.CreaeteDataSet initially without ReadOnly flags solves the problem. After opening ClientDataSet fields' ReadOnly flags can be returned to their seats for the proper functioning of data-aware controls.

odbc datasource connection at runtime through delphi

can we create ODBC datasource connection at runtime? If yes then can you plz help regarding how to do it.
Currently I am created the ODBC datasource connection manually through Control Panel--> Administrative Tools --> Datasources.
But i want to create that at runtime when user run application.
thanks for the help.
You can use SQLConfigDataSource (Delphi example).
Yes, you can do it. As #TOndrej points out, you can create a ODBC datasource at runtime. But usually you don't need to. You might just create a Data Connection in runtime without an ODBC datasource.
Something like this, using ADO components to a MS Jet OLE DB ...
if ADOConnection1.connected then ADOConnection1.close;
ADOConnection1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;'+
'Data Source='+filename+';'+
'Persist Security Info=False';
ADOConnection1.LoginPrompt:=false;
ADOQuery1.Connection:=ADOConnection1;
ADOConnection1.Open;
....

Resources