I actually try to do an insert on a ADODataset linked on a table with an auto-generated GUID.
When I try to get the new ID of my record I get some zero for GUID.
This is an old question but if anyone comes across it...
The big advantage of using GUIDs is that you don't care where they originate from. A value generated as part of a default constraint is no better or worse than a correctly generated GUID in a client program.
#Ravaut123 is correct in that you should just set the GUIDs value when inserting on the TADOataSet set
Related
Hi I have a domain class that I set as int userID. Will it affect when the auto number become very big that User.findById() throws error? If I change to Long now (people are already using the application) will it affect the findById()?
findById() will work just fine.
The real problem will be when inserting new data into a table, if the id is auto-generated, it, most probably, will restart when reaching the max value which can result in duplicate ids, and hence, errors.
In general, is not that easy to alter the schema definition when the app is already in production and the DB is populated. And if you try to do that in Grails, you have the risk of losing information in the DB. So please, do a backup, before trying anything.
I have a (Firebird) DB. For most of my tables I have a trigger which fires before insert which will create the Primary Key (PK) for me via a generator as well as write to the newly inserted records a Created Date value and a Created By value. I also have an update trigger which writes to an Updated Date field and an Updated By field.
eg (Client is a table in my DB):
create trigger t_client_id for client
active before insert
as begin
new.client_id = gen_id(gen_client_id, 1);
new.created = current_timestamp;
new.created_by = current_user;
new.lock_vn = 1;
end ^
create trigger t_client_update for client
active before update
as begin
new.updated = current_timestamp;
new.updated_by = current_user;
end ^
When I apply updates thru my ClientDataSet (CDS) - which are attached to remote TDataSetProviders via a TDSProviderConnection, how can I "retrieve" these generated values? If I edit an existing one (which will in turn call the t_client_update trigger, calling RefreshRecord will get the updated and updated_by fields. However, the Doco says to use that method cautiously, so that may not be the correct way to achieve this. I call it straight after I've called ApplyUpdates(-1).
The CDS I use only contains the one record I am attempting to Edit. For a New record, the CDS is in dsInsert mode. Everything is written to the DB ok so I just need to get this new data back out again. I have also tried using a CDS which contains ALL records in the table too to see if it was any simpler but didn't make any difference - unsurprisingly. The reason I need this information is simply to show to the user in DB Aware controls these values. They are read only.
I could call a Get on the record I guess when editing an existing record, using the PK, but that won't help for an Insert as I don't know what the new PK is.
Example of where I attempt to ApplyUpdates to my CDS (actDSSave is a TDataSetPost action)
dsState := actDSSave.DataSource.DataSet.State;
DoApplyUpdates(-1);
if dsState = dsEdit then
TClientDataSet(actDSSave.DataSource.DataSet).RefreshRecord;
I am using TIBQuery for my dataset attached to the remote DataSetProvider. This query SQL is a simple select * from client where client_id = :client_id. I have tried associating this query with a TIBUpdateSQL too as well as trying to set poAutoRefresh to true in the DataSetProvider.
So is it possible to obtain these Trigger generated values this way or do I need to approach it in a different way? Another way I can think of, is to create stored procedures which do CRUD against each table and use that instead (with appropriate in/out params to return this new data) but hopefully I don't have to go down that track. Hopefully I have provided sufficient info here to explain and replicate the issue.
Thanks
EDIT
Realised in above, DoApplyUpdates(-1) is my own method. It's implementation at the moment is simply:
FdatCommon.cdsClient.ApplyUpdates(MaxErrorCount);
FdatCommon is a TDataModule containing my CDS.
You simply can't get "generated" values without new requery (RefreshRecord) of data after Post.
It's because triggers runs on server side when you call ApplyUpdates, but TClientDataSet does not refresh by default posted record. For example other libraries FIBPlus have an option to do it automatically.
About inserts, TIBDataSet have GeneratorField property. Using it, dataset query and increment generator value separatelly before insert. So you will have PK values after post even on inserts. But avoid using it again in trigger.
MIDAS (TClientDataSet) is a great library, but his general / universal architecture loose DB specific features (such as retriving values from inserts) compared to dedicated libraries for specific DBMS, such as FibPlus. By the way I saw TpFIBClientDataSet. It work in conjunction with TpFibDataSet.
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.
Is there a way to auto increment a number field in a WITT (e.g. Bug). We've got a requirement that we want contiguous Bug ids (note - not its actual id but a separate field).
Can this field be done unique per collection OR unique per project (thus duplicates would occur in the collection).
---edit
I've no idea how to tackle this, but I'm wondering if I could use a globalist, e.g. bug creation triggers the adding (replacement) of a value to the list?
There is no way to do this directly through the WIT platform. You would need to write some sort of custom service to do this for you on the creation of a new bug.
My answer goes into the same direction like aaronbjorks one.
Create a webservice that gets alerted if a new bug is created, then just write down the bug ID in a database with an identity column. On the workitem you can create a custom control, that gets the identity for that bug from the database and displays it somewhere.
A possible workaround would be exporting your items query to Excel and let it update the IDs upon Publish. Make sure once an ID was assigned, tag it as FROZEN.
In LINQ to Entities, I map the result set of a stored procedure to an entity.
Within the stored procedure, I execute some update statements and return the result set by running a SELECT query and mapping that result set to the entity.
The database rows get updated correctly, but the entities returned are not reflecting the changes. Instead, the data before the update is getting returned?
Any suggestions?
Thank you.
Abe
Actually, it turns out the DataContext.Refresh method solved my problem at
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.refresh.aspx
Here's my code:
db.Refresh(System.Data.Objects.RefreshMode.StoreWins, affectedProjectTasks);
Thanks Marc for pointing me to the right direction!
Abe
Are the entities in question already cached in the context? (i.e. have you queried them already?)
If so, the identity manager will always give you back the original object (rather than creating a new object with the same identity in the same context). Hence for data that has already been read (by other queries) only the identity/primary-key field(s) are considered.