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.
Related
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!
Im working on an azure database just adding a couple of Stored Procedures and just making sure the program I'm building with it in .NET is all aligned properly.
I'm not going to go into the Stored Procedure itself nor the Program I'm developing because I don't believe the problem is there, I have a Development program and database which is using the exact same code and they work fine, I'm using Microsoft's SQL Server Management Studio to handle everything on the servers side.
The only difference to the current setup is that I myself scripted a bunch of the Stored procedures and a single View of a table that I did not create....(I did not create the table, but I made a view for it which is a slightly different format)
The person creating most of these databases and table is one of the database administrators I guess (not Microsoft, but an employee of the company using their services), I on the other hand am a freelance programmer and I'm guessing I have somewhat limited access to the server (limited credentials).....although it's allowing me to do more or less anything I need to do like creating SP's etc.
My current (and only problem) is a single stored procedure that runs through without an error does not update the table (the table i did not create) the Stored Procedure just inserts a couple of records and then deletes a record from the same table.......
It deletes the record just fine but for some reason the INSERT doesn't insert anything.
Again, this works fine on another Development database and the programs are sending the exact same strings but this new database just doesn't want to play along.....
Could this be a permission problem I'm having between my stored procedure and the table I did not create?
I would love to dump this onto the admin guy (and already did but he dumped it back on me haha) so I just want to be sure I'm not wasting his time....... and give him something solid to go on.
Thanks for your help Paul S.
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
I have a bit of problem here. I have created a lookupfield in my application server using Delphi XE2 DataSnap technology. On the client side, that field becomes TStringField. Now, the problem is that I loose the lookup functionality on the client side. To top that, I can't change the stringfield on the client side because it is read only (even if I manually turn off the read only property).
I don't want to lookup tables on the client side because I don't want all the data loaded on my client side just to support look up.
I can change the Key field value, but the stringfield lookup text doesnt change unless I apply updates and reload the data.
Users want to see the text change.
What should I do?
Seems you have to review your GUI functionality: lookup fields are really an client side feature. And it needs the lookup source - so to use it on client the lookup table must be loaded. DataSnap guys are very nice here, converting it to an TStringField when transmitting it to the client... I would simply ignore it.
So, if the lookup table is that big, you shouldn't using lookup fields but search UIs - or autocomplete comboboxes which you do queries against the DataSnap Server. Maybe you have to code it manually in the combobox case, I don't know (see if JVCL have something you can use to shortcut the path).
Alternatively, if the lookup table are seldom updated, you can aggresively cache it and have an updating mechanism to detect changes. So you can use the lookup fields the way they were created for.
Long time ago i faced that problem and i found a solution that is a bit complex to analyze here but i try to give some guidelines till i have the time to write a detailed blog post.
The idea consists of info (concerning lookup fields such as field properties, datasets, providers) packaged by the provider as optionalparams at the server side.
At client side a derived TClientDataset can unpack and process these info, create on the fly client datasets that retrieve needed lookup datasets and setup it's lookup fields accordingly.
The process is transparent due to the embedded functionality in the derived client dataset class and the only things to remember is to create that info in the provider's OnGetDatasetProperties event and turn false all provider flags in lookup fields.
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.