Using ConnectionString instead of TAdoConnection on a TAdoQuery - delphi

I have derived my own component from TAdoQuery in Delphi. I have overridden the DoAfterPost procedure; and in this code I create another query for the purpose of fetching the primary key associated with an inserted record (i.e. SELECT ##IDENTITY for SqlServer, SELECT LAST_INSERT_ID() for MySql, etc).
In the past I always used TAdoConnection for database connectivity. And in the "subquery" call made within DoAfterPost there was no problem because it was the SAME Session (these queries to retrieve last inserted primary keys assume a persistent database connection).
I recently made an option where instead of using a TAdoConnection connection, I am instead setting the ConnectionString property (for multi-thrading purposes). But this creates a problem because the spawned subquery does not use the same session as the main query. Hence it does not return the primary key value.
My question is, does TAdoQuery have any Connection property if the ConnectionString is used? I could then daisychain this connection/session to my subquery. Or is the only way to accomplish this via a TAdoConnection?

#M Schenkel, when you set the ConnectionString property of the TADOQuery component, the TAdoQuery create a new connection to the database with a new session id.
the ##IDENTITY SQL Server function return the last-inserted identity value in the current session , because that you need to use the same Connection (and session) for the insert statement and the query SELECT ##IDENTITY.
As workaround in sql server you can use the IDENT_CURRENT function wich is not limited to an session.
In MySql the LAST_INSERT_ID() function also works on a perconnection. therefore the behavior is similar to the function ##IDENTITY.
In short, the best option you have is to use an unique TAdoConnection object.

Related

Change BOOLEAN to LOGICAL in generated sql script by FDTable

I have a FDTable with TBooleanField.
The database is dBase IV.
I want to create the table with:
<TFDTable>.CreateTable(False, [tpTable]);
This works if I don't have a TBooleanField in the table.
In the SQL script that generated on CreateTable the TBooleanField is of type BOOLEAN. Is there something in property of FDConnection or FDTable that change the BOOLEAN to LOGICAL.
SQL Script:
CREATE TABLE ACT_01 (
ISDOC BOOLEAN,
DOCTYPE VARCHAR(1))
Must change in:
CREATE TABLE ACT_01 (
ISDOC LOGICAL,
DOCTYPE VARCHAR(1))
Ok, I can execute the sql myself without the createtable but I want to know if it is possible to change the BOOLEAN to LOGICAL from the methode TFDTable.CreateTable
FDConnection:
FDConnection1.Params.Add('DriverID=ODBC');
FDConnection1.Params.Add('ODBCDriver={Microsoft dBase Driver (*.dbf)}');
FDConnection1.Params.Add('Database=C:\Projects\Test Projects\DBase table\Data');
FireDAC uses hardcoded data types for generating CREATE command for all unsupported ODBC drivers (the ODBC command generator's GetColumnType method doesn't query driver for DBMS data type names).
What's more, FireDAC does not recognize any ftLogical data type, so you cannot create a custom data type mapping even though that's just what you were supposed to do here.
So, you're out of luck at this time.

Create a .mdb without MS Access or ADOX

I'm using dephi 2010, which is getting difficult with me about installing the ADOX components. So I was wondering if there is a way to create a .mdb file without the use of the ADOXCatalog.
-Thank you.
Yes, this can be done without using an ADOXCatalog.
Place a TAdoConnection and e.g. a TAdoCommand on a form or datamodule. Set the TAdoCommand's Connection property to the TAdoConnection.
Then, in the AdoConnection's ConnectionString builder, select Microsoft OLE DB Driver for ODBC. Then, follow the ODBC wizard to set up a new MDB database. As you follow that through you will be able to create a File DSN (unless you are running Delphi as adminstrator), select the Access Jet driver, specify the database path (making sure it is somewhere writeable) and name, and then the wizard presents you with a button to click to create the MDB file.
Although it is not in English, there is a video here
https://www.youtube.com/watch?v=E_2hrER9oho
which shows you exactly how to do this. The ODBC connection string wizard should give you the option to create a new datasource and present you with a list like this to choose from:
Set the TAdoCommand's CommandText to something like
create table ATable (AName TEXT(40))
and call its Execute method at r/time to create a one-column table.
Btw, you could equally well use a TAdoQuery instead of the TAdoCommand component using its Sql property instead of the TAdoCommand's CommandTextproperty, and you should be able to use any valid DDL statements to define the tables in the database.

Prevent synchronization of identity column when inserting with EntityFramework

Using EF4 /w SQL Server 2008.
The following code (against a table with a PK, defined as Int IDENTITY(1,1):
ctx.AddObject(GetEntitySetName(), newEntity);
ctx.SaveChanges();
The results when profiling SQL are the insert statement following by a lookup against the table I'm inserting into:
SELECT ID FROM Table
WHERE ID = ##ScopeIdentity AND ##RowCount > 0
Is there a way to prevent EntityFramework from retreiving the Identity seed? I don't need the ID back in my .Net code and under high volume situations it seems like a wasted operation.
Altenatively, is there a way to tell EF to change the way it performs this operation? The strategy used goes against recommendations made by Microsoft in this defect report:
http://connect.microsoft.com/SQL/feedback/ViewFeedback.aspx?FeedbackID=328811
You cannot change this behavior when using database generated keys (properties marked with StorgeGeneratedPattern.Identity). EF needs a real key value for inserted entity so the only way to avoid the query is to not using database generated keys at all and handling it yourselves in the application.

How to reset Delphi Tadocommand parameters

I have a Tadocommand on my datamodule which is connected to a MSSQL storedproc. The storedproc is used to update a table.
In my code I call the the tadocommand in the beforeupdaterecord method of one of my Tclientdatasets.
first I supply values to the tadocommand parameters using the deltads.fieldbyname().newvalue of the Tclientdataset then I call the execute procedure. It works ok for the first update but if i try to do a next update it generates "error changing varchar to datetime".
if i dynamically create the tadocommand in the beforeupdaterecord method i.e
sp1_editcontract:=Tadocommand.Create(nil);
sp1_editcontract.CommandType:=cmdStoredProc;
sp1_editcontract.Connection:=DMDBconn.DBConn;
sp1_editcontract.CommandText:='EditContract';
sp1_editcontract.Parameters.Refresh;
//assign parameter values
sp1_editcontract.execute;
sp1_editcontract.free;
it works without any errors. I think there is some problem with the parameters values when using the static Tadocommand on the datamodule.
why does multiple update generate an error when using a static created tadocommand and not for the dynamically created tadocommand?
I'm going to assume you are referring to TDatasetProvider.BeforeUpdateRecord and not TClientDataSet.BeforeUpdateRecord.
Its kinda hard to say from the information you've provided (you don't indicate the data types or order of the arguments for the stored procedure). The error message is coming from the SQL Server engine. I would make sure the values being assigned to the parameters are always being set in the correct order. Also try to identify which parameter is causing the error. If you can reliably reproduce it in your client code you may try calling the stored procedure in SSMS passing the same values that are causing the error in the client application.
Once you identify the parameter you can check that its datatype is consistent between the ADOCommand, DatasetProvider and ClientDataset. If it changes type along the way that may be the cause of the error.
One last suggestion, make sure you set TDatasetProvider.Applied := True before exiting the BeforeUpdateRecord handler. This prevents the dataset provider from trying to apply the update using dynamic sql after you've already applied the updates. If the data in the client dataset was populated by a TADOQuery it may be attempting to update the tables directly.
I had a similar problem. In order to clear all the existing parameters of the ADOCommand before adding new ones a used the following code:
while Command.Parameters.Count>0 do
Command.Parameters.Delete(0);
Parameters.Clear should had worked, but it didnĀ“t, so I decided to remove the parameters one by one. That fixed to me.

ASP.NET With Firebird database problems

Did you ever try to create a ASP.NET MVC Project with Firebird database...I try it, and is difficult..
My problem:
I have working Firebird provider for Visual Studio 2010.
I have correct database with all needed for increasing the id of the tables.
I have created ASP.NET MVC 3 project, with included database, like EDMX file, with entities.
When i try to insert a record into a table, there occurs a problem that says:
FirebirdSql.Data.Common.IscException: violation of PRIMARY or UNIQUE KEY constraint "PK_USERS" on table "USERS"
That means the id of the record that is created is not increased.
I have stored procedures that must generate new id.
My question is:
How to insert record in Firebird data table from ASP.NET?
In Firebird you need to use triggers in combination with sequences (generators) if you want to have auto-increment like behavior. Otherwise you need to make sure that you assign a unique id yourself.
To create the sequence:
CREATE SEQUENCE mytable_id_sq;
To create a trigger for assigning a unique i (on a table called mytable)
set term !! ;
CREATE TRIGGER T1_BI FOR mytable
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
if (NEW.ID is NULL) then NEW.ID = NEXT VALUE FOR mytable_id_sq;
END!!
set term ; !!
This trigger will only assign a generated value if no ID is assigned in the INSERT statement.
See also:
section SEQUENCE (GENERATOR) in the Firebird 2.5 Language Reference and How to create an autoincrement column? (this link talks about generators, the old name of sequences in Firebird).
Your EDMX isn't probably generated properly. Either you have to set the StoreGeneratedPattern manually or use http://blog.cincura.net/230841-generated-primary-key-in-entity-framework-model-from-firebird/ .

Resources