I have two table where the datasource gets updated once we update the record in first table and push to second table which is the updated record called from service, simply both the tables will have two service calls; the service returns the response correctly but the table is not getting updated in frontend
1- You need to use OnPush strategy in your component
2- if 1 not work so You can use change detector from ChangeDetectorRef in your component
3- if 1 and 2 not work you should know to practice pipe async with behavior Subject and observables
Related
currently, my DbGrid uses a view that map directly to a table in the Database. (SQL Server 2012 and up)
Now I needed some readonly extra informations in my table so I need to implement a UNION in my view. I created the new view "WITH_METADATA" and implement for all operations "INSTEAD OF" triggers.
It works mostly but sometimes on little changes when I post the data I get the error
row cannot be found for locating
I tried all variants of this in the QueryBeforePost event.
Query.Properties['Update Criteria'].value :=adCriteriaKey;
But it doesn't change anything.
I want to apply CQRS pattern in a project but i don't understand how can i join and denormalize data.
Consider a data model where there are 2 entities: Product and Store in a many to many relationship and an attribute named stock (the product quantity in a particular store) as a relationship attribute.
Consider also that I already created 2 microservices:
ProductService: responsible to handle CUD operations on products;
StoreService: responsible to handle CUD operations on stores. The entity ProductStore is managed by this service.
At this point, I want to create a third microservice that is responsible to join the data of ProductService and StoreService in order to retrieve all the available products. Here, CQRS pattern seems like the best solution: I will create a materialized view and I will synchronize it using domains events published by the other 2 microservices. Great!
And now the doubts.
Suppose the materialized view has the following columns:
product_sku, product_name, stock, store_name, store_address.
When I update a Product entity or Store entity there is no problem to sync the view because I already have data on it. But what about when I receive a ProductCreated event? This event has only information about product and nothing else, so stock, store_name, store_address will be NULL. How can I save this event in my view? Should i save incomplete data somewhere else and update my view when I will receive complete data?
Thanks!
CQRS , Event sourcing and Materialized view
Your are right, Generally CQRS , materialized view goes with Event sourcing pattern. Which means that we keep on adding our events into event store (this is single point of truth). We generate materialized view by scheduling the job that would read the data from event store and create/update materialized view or we can generate the materialized view following by event trigger. So when you would get store service event (that's probably after product event) then you know that's your last event for particular transaction and query event store to update materialized view and you will have all the data. In short keep dumping in event store and query at once your event store to update your materialized view. Adding event source itself can be complicated so don't over complicated if you can mange without it.
Your case
If you are not using event store then in your case you save the partial/incomplete information in the Materialized view and keep updating it when other inflight events arrive. You will have single reference/key against which you will be updating your data in materialized view. Since the whole system is eventual consistent you will have to manage how would you like to display incomplete (if you have to) data on frontend or you can flag it if you don't want to show (unflag when last event arrives and information is complete).
Materialized view
As an example:
I have two tables in firebird:
TB_CUSTOMER
IDCUSTOMER (autoincrement generator)
CUSTOMERNAME
TB_PHONE
IDPHONE
IDCUSTOMER (foreing key from TB_CUSTOMER)
PHONE
I have a registration form developed in Delphi. The table data TB_PHONE are handled using a dbgrid. I can not assign the value of the field IDCUSTOMER in TB_PHONE, because it was not generated by the Firebird generator. How can I make the relationship between the tables? I want to implement it without first saving the table data TB_CUSTOMER. I'm using datamodules with IBDAC.
Any sugest?
Before detail table can be inserted into, you should have PK-index over master-table updated and having proper master-ID in it. That means that some piece of code should insert master-record before inserting detail-record. Where this piece of code would be - is only limited by your fantasy.
Few arrangements include
insert the master-row in your application. Read the id of the row. Insert detail-row using this id.
read ID from then Generator, then insert both rows (master 1st) using the obtained ID
create a stored procedure, inserting both rows and returning ID (implementing #1 or #2 server-side)
use EXECUTE BLOCK - basically ad hoc anonymous SQL procedure. But that only is available in FB 2.x and except for not using namespace it is inferior to #3.
add BEFORE INSERT trigger onto detail table, searching for ID in master and adding one if not found. This would slow down all insert operations (even when master-ID already exists - that should be checked), would not be able to fill all other master columns but ID and is potentially dangerous due to hiding application logic problems. But still that can be implemented (though ugly and dirty method)
create master-join-detail VIEW and add INSERT trigger for it, propagating the new view-row into both master-table and details-table.
et cetera
I want to implement it without first saving the table data TB_CUSTOMER
There's your problem. You need the primary key from the master table before you can save the detail. That's just the way it works. But if what you want is to make sure that the values get saved together, you can do that as a transaction. In Firebird, you can do it like this:
Begin a transaction. Exactly how you do that depends on which DB library you're using to access your Firebird database.
Run an INSERT INTO ... RETURNING statement to insert the row into your master table and retrieve the generated value as a single operation.
Use the generated PK value to fill in the FK value on your detail table.
Insert the detail row.
Commit the transaction.
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 would like to have a page that checks for updates to a database table and refreshes the grid using an Ajax call and when a new row is inserted into the table pop up a message window.
This database table gets updated with new rows every 15 minutes or so and the message window lets the user know that a new record has been added or possibly more than one record.
I'm wanting to do this in ASP.NET MVC with Ajax but have no idea how to go about setting up the javascript to check for updates on a timer or if there's a flag that the XHR uses to indicate a change in state.
You should try PokeIn library. It helps you to notify connected clients based on server side events. Here is a basic scenario;
Single static timer runs on the server side and checks any changes on DB. If an update is available sends it to connected clients / associated groups etc.
Samples are available from
This could be a possible way to do it:
Store the time when the data is aquired in a global variable in javascript.
Every x minutes, you do a javascript call to an action method with the timestamp as parameter. This can be done for example using the jQuery Timer as suggested by Rony.
The action method checks the database to see if anything has changed or not, and returns a simple boolean 1/0.
If, and only if, the data has changed, you get the new data from another action method and notify the user that new data has been retrieved.
you can use jQuery timers to check the state of the database using ajax and then modify the values in the table accordinly