FireDAC TFDTable.Post vs TFDQuery UPDATE clause commt - delphi

Using FireDAC in Delphi 10.2 to a Firebird 2.5 database, seeing a behavior I don't understand.
I open a TFDTable, Locate a desired record, call Edit and update some fields in that record and then call Post. If, after doing this and while the program is still running and the DB connection open, I open the DB in FlameRobin or other external data viewer and view the table, the changes I posted aren't visible in that external viewer and don't become visible until I close the DB connection as the program terminates. If I instead use a TFDQuery and normal transaction handling to UPDATE the same fields via SQL statement, the changes become visible in the external viewer immediately after the transaction is committed and I refresh the external view.
TFDTable.CachedUpdates and Exclusive are both False; Fetch, Field and Update options are at defaults; and UpdateObject and UpdateTransaction are unassigned.
What am I missing here? Thanks!

Related

Local Firebird Table Editing

My application was coded under Delphi XE5 + Firebird-2.5.6, client / server. ZeosLib.
If I want to edit a record like this:
ZTable1.Edit;
ZTable1.FieldValues['champ1'] := Edit1.Text;
ZTable1.Post;
I wanted to know if this code on the local network, could it have worries or a conflict of editing and post please? That is, editing the table by multiple users will not even have an impact or an error message that pops up at those users. If yes, how to avoid this inconvenience please?
Thank you for your help.
It depends on the action with this record that will make the other user and how long your transaction will be active.
For read or after commit or rollback your transaction will be no conflict
Before a transaction end for editing or deleting the record of another user may lock a message or if a user transaction is started with no_wait flag, waiting edited transaction completion
P.S. Zeos for Firebird is a very straingth choice. Why you not uses standard IBX library?

Data Refresh From Database when using TADOQuery, TClientDataSet, TDataSetProvider in Delphi

I have a TADOQuery connected to a database, and sql set to fetch data.
TDataSetProvider to the above query
TClientDataSet connected to the provider
TDataSource connected to the Data set
Data source connected to a TcxGrid
The Client Data Set is also connected to a master source, that in itself is connected to a table.
I am able to add and delete to grid as expected (grid cannot be edited directly, all people can do is add or delete). I am using delete and append on the data set to control the grid.
What is strange and I cannot solve is that when I change what record is being used in the master source grid, and then go back to the original record the data is being refreshed from the database or some stored original state of data set, rather than the in-memory data set.
So if I had deleted a record, it reappears, and any still existing ones are duplicated, though anything added from last save to database is not duplicated. However if I do an update on the data set to the database, the database table is how I would expect. No duplicate records, anything deleted via grid/data set is deleted, anything added is added.
I suspect this is a really trivial flag setting, but I cannot find this, and every query others have seems to be about refreshing the data, not preventing it.
Any suggestions would be appreciated.

Best way to manage Listview items from Indy 10 thread

I'm making a multi user remote administration tool, a sort of VNC but which support multi remote desktop viewer a bit like Teamviewer does.
I have a Delphi Form which only contains a TListview, this listview contains users list which are currently connected to the server.
When a connection is dropped, the listview item is deleted.
For some reason I got some random problems while deleting more than a single item, for example if I decide to flush the whole server connections, if I have more than 1 listview item, it start going crazy.
Sometimes no error show up, just some items remain listed, sometimes it shows "address violations errors".
As I was before using pure Winsock API to make Client / Server application, I maybe use badly Indy components.
A short explanation about my way of managing the Server component.
My application is Multi Server, which means user could create one or many servers at the same time.
When a new Server is created by the user it run a new thread which will create a new indy Server component and setup needed events (OnConnect, OnExecute, OnDisconnect) etc...
Every commands that acts with some VCL form are of course Synchronize using the Synchronize(); delphi method.
When a new connection show up, i create from the Server Execute method a new listview item, then i set the new listview item to the AContext.data property.
When a connection is dropped on the OnDisconnect event, I delete the listview item then empty the AContext data to be sure, he wont do it again when he will be automatically destroy.
Synchronize(procedure begin
TListItem(AContext.data).Delete;
end);
AContext.data := nil;
This way of doing works very badly when I have more than a single connection. After debugging it seems even with the Synchronize commands are executed at the same time which could result conflicts in the VCL form.
I'm not an expert in Indy10, any advice would be surely appreciate.
Usually it is not a good idea to store your data in the UI.
Alternative answer on how might want to organize this:
Store your users list in the business layer of your project.
Display the users using a virtual model listview that obtains the data from the business layer. See for instance the answer at https://stackoverflow.com/a/4233875/29290
Access that data in a thread safe manner (locking, etc)
In the Indy 10 thread, access the data in a thread safe manner (locking, etc)
Have the business layer notify the Indy and UI portions of changes in the data

How does a client refresh the data on a server

I developed an Client/Server application, using datasnap. I need to know how to refresh the data on the server whenever a client has updated a table. The reason being that when I run a query on the client, after I inserted records into a table, the new records do not reflect in the queries.
Im using a firebird db, with datasnap, developing in Delphi XE2
Put a TTimer control on the client form and specify refreshing time frequency, change interval value as your needs, for example:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
table1.refresh;
end;
I would say, it also depends on tools you are using to write to DB.But, generally, with Firebird, you would Activate a Transaction and once update is done you would then Commit your changes. Prior to committing, no other client can see the new Changes no matter how many times they refresh. Once committed, my understanding would be to say, you would then Refresh you data by merely calling a SELECT command, as per your criteria.

Tracking or Notifying DB Changes - Inserts and Updates mostly

How do I track or get notified whenever a record is inserted or updated in a DB? I would like to notify an external application of the changes in near real time whenever such changes in DB occur. Are there DBMS independent and application programming language independent ways of doing this? If not, then is it possible with MS Access and MS SQL Server in particular? I'm looking to avoid continuous polling of DB of course.
With SQL Server it is possible to load a DLL within SQL Server itself and call methods from this with extended stored procedures. The DLL could then notify other applications - usually via a TCP socket.
I think the latest version of Microsoft SQL Server allows you to raise events in your .NET code based on server conditions and events. I haven't tried it, and I haven't heard of any 'DBMS independent' way of doing this (without polling DB every X milliseconds).
With MS-Access, I keep track of record changes or record additions with fields in the main table that store the user name and date when the record is created or updated.
You need to use a windows API to record the user name, usually run when switchboard form is opened.
I am digging to find a away to track specific changes. My data base is used for project management. I would like to keep track of what specifically was changed, not just who and when that I have now.
I think this meets the requirements of the original question. I can later add the windows API that reads the name of the user.
Private Sub Form_BeforeInsert(Cancel As Integer)
Me!UserCreated = UCase(CurrentUser())
Me!DateCreated = Now()
End Sub
Private Sub Form_BeforeUpdate(Cancel As Integer)
Me!DateModified = Now()
Me!UserModified = UCase(CurrentUser())
End Sub
-- Mike
To do this with SQL Server, you use the Notification Service - write a dll that subscribes to notifications from the DB for data updates which you can process in some way.
However, MS has said that they are removing this from SQL Server 2008.
Oracle has something similar (though they tend to leave their technology in place), but I've not seen anything that is database-neutral.

Resources