Azure Offline Sync Updated At pulls whole data during the Incremental Sync - c#

I have a table controller, which has one way sync (Only get since there is no any update from mobile). So the very first time when I do the PullAsync it has pulled whole data since my Update At filed has the same timestamp for all the records. Now Second time I just wanted to do the incremental Pull (Note I do pass a name value to PullAsync to enable incremental sync).
But the problem is, it retrieves whole data again since there is no updated time stamp in Updated At (Because there is no update method in the Table Controller since it is one-way sync-Azure to mobile). How can I omit pulling data again if there is no update while all the Update At values are same time stamp? The issue is same as mentioned in below link. Do we still need to do one record update in order to fix this?
https://social.msdn.microsoft.com/Forums/office/en-US/ff002e85-1313-449f-89eb-cd45c1a4846c/mobile-services-sync-pullasync-and-updatedat?forum=azuremobile
Thanks in Advance

How can I omit pulling data again if there is no update while all the Update At values are same time stamp? The issue is same as mentioned in below link. Do we still need to do one record update in order to fix this?
I have checked that this issue still exists. AFAIK, the PullAsync operation would pull 50 records (MaxPageSize by default is 50), then begin a transaction to insert / update the retrieved entities, then update the local __config table with the latest updatedAt timestamp, then try to retrieve next page records and execute the above processing again.
Note: The format of id column looks like this deltaToken|{table-name}|{query-id}.
The pull operation request would look like:
https://<app-name>.azurewebsites.net/tables/<table-name>?$filter=(updatedAt ge datetimeoffset'2018-02-21T08:58:45.446Z')&$orderby=updatedAt&$skip=0&$top=50&__includeDeleted=true
I assume that you could query the local __config table to retrieve the latest updatedAt value or query the related local table to retrieve the latest updatedAt value, then add a small time interval to the current updatedAt and explicitly specify the filter on UpdatedAt property with the previous updatedAt when using the incremental pull operation.

Related

DateTime syncing issue in Azure Mobile Services

The problem is I have 2 columns CreatedAt and UpdatedAt in text data type in local sqlite and on server these two columns are of datetimeoffset data type.
When I insert/update any record using MobileServiceClient of azure, everything gets into database except these two column resulting in NULL values.
Similarly, if I update these column using SQLite connection, it updates records just fine. However, azure does not take these two columns' values on server when I sync.
Things I have tried:
Inserting every possible format of date time in these columns, which I thought is the problem.
Changing column's data type to match the data type on server but MobileServiceClient inserts default date and time which is 01/01/0001
I'm having trouble understanding how this service handles the data locally and on server.
Any help?
When creating the table on the server, it used to set those two columns up to get values automatically, not populated from the client.
The DDL for the columns looks like this:
[createdAt] datetimeoffset(3) NOT NULL DEFAULT (CONVERT([datetimeoffset](3),sysutcdatetime(),(0))),
[updatedAt] datetimeoffset(3) NULL,
and there is a trigger for updatedAt:
CREATE TRIGGER [DbName].[TR_TableName_InsertUpdateDelete] ON [DbName].[TableName]
WITH EXECUTE AS CALLER
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
UPDATE [DbName].[TableName] SET [DbName].[TableName].[updatedAt] = CONVERT (DATETIMEOFFSET(3), SYSUTCDATETIME())
FROM INSERTED
WHERE INSERTED.id = [DbName].[TableName].[id]
END
GO

getting "DateTime" of the last change in rows in a table in SQL Server?

Is there any way to find "DateTime" of the last change in rows in a table in SQL Server?
The changes (Insert / Update) are submitted by another windows application
And all I have in this table is insert_Date and there is no update_Date (and I can't add any columns or use triggers)
I've tried some queries, but all I got was the number of "User Updates" in a table, not the IDs of modified rows!
I want to get rows which are modified or inserted after a specific DateTime
If the information isn't stored in the table (or in another one by using a trigger for example) then it's impossible to track which rows were inserted after a determined datetime. You might find the time the last operation was executed at a table/index level (by querying sys.dm_db_index_usage_stats) but not at a record level.
You can't find data that doesn't exist!

How to know from client side if table was updated

I am building a C# Winforms client connected to a MySQL database. The client will be accessible from multiple users and computers. I need a way for all the clients to somehow be notified whenever another one makes a change to database contents so to refresh in the client.
Since when a user opens a form that shows database contents, the contents are fetched at runtime. So that is not the issue. If an update is made the user will see it.
My problem is if a user has a form of database content open and another user changes database content.
I thought of setting up a timer of some sort and every minute get all the database contents that the user is currently viewing. But that is very time consuming and not efficient at all.
Another thought was every minute check for updates but I do not know how to implement that.
Any suggestions?
Is there a way to get check for updates from client side?
Is there any other way to perform this?
What you could is change your table so it stores the timestamp whenever it is updated.
For example
CREATE TABLE foo (
id INT PRIMARY KEY
x INT,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP,
KEY (updated_at)
);
The above code store the current timestamp to a new row and changes it the time edited whenever a row is edited. This way you can get the data, sort it (order by) in descending mode and get the top record. That way you get the last updated record in your table.
If you want to know for the whole database then you have to compare the last updated record for each of your tables and get the most recent one.

Allow multiple users to update same record

I have a situation where there is one record in database table i.e. 'abcde'. And User 'X','Y' and "Z' tries to update that record at the same time.
'X' modify abcde to abcdd
'Y' modify abcde to abddd
'Z' modify abcde to abeee
All changes should persist in database table.
Is it possible than please provide the solution.
If you want to persist all changes, then you will need at least one more database table that keeps track of all these changes...a log/history table.
The question is, how do you want to handle concurrency? If you don't care about it and you only want to keep the last modification in this single record table, then you don't need any further action, except the "logging" functionality that keeps track of all changes.
But, if you do care about concurrency and want to handle it in a different then you should look at running transactions with the isolation level that best suits your needs
As you want to log the updated records only for the concurrent case . Have a column of DateTime in the table and when you display the record to keep the track of datetime. So here is the use case.
First User updated the record -> Update the original record withchange in DateTime column value also.
When Second User try to update you found that datetime has been changed , it means it is no more Update , it will be an inset statement.
It will be similar case of 2 for third user.
Now you are left with all the three records in the database.Remember in this case Primary key need to have some incremented column also otherwise it will throw an error.
You can use Trigger and save records in another Table for every operation. Capture data Change(CDC) will also work in your situation.

How to retrieve an audit trail across two SQL Server tables and put them back in the right order?

Background Context:
i have a database table called Project and a table called ProjectHistory with the same schema. I am using nhibernate so i also have a domain object called Project and a domain object called ProjectHistory (which derived from Project).
Goal
My goal is to retrieve data across these tables and put them back in order as the events that happened and have C# code output a typical audit trail screen of last n number of changes
Details
Both tables have the following fields and data types
Id -(int )- primary key in Project, NOTE: no PK in the history table
LastUpdated (datetime)
Name (varchar)
Description (varchar)
Timestamp (timestamp)
the goal of the Projecthistory table is that whenever i do an update to the Project table, the ProjectHistory table get inserted a new row with the old record so i can have a full audit trail.
I accomplish this through using this trigger:
ALTER TRIGGER ProjectTrigger
ON Project
AFTER UPDATE
AS
SET NOCOUNT ON
insert into ProjectHistory
select * from deleted
My issue is that i now need some C# code to put together an audit history where a user select the most recent n number of events.
Example:
Here is an example of events:
On Jan 10 - create project 1 (nothing in history yet)
On Jan 11 - create project 2
On Jan 15 - edit project 2 ( will put entry in history table of project 2 with Jan 11 date as lastupdated by)
On Jan 25 - edit project 1 (will put entry in history table of project 1 with Jan 10 date on it)
so, as you can see if i sorted descending by lastupdated field in the history table, it was put the result from event 4 before the result from event 3 which is out of order.
Code
I have tried the following code to try to put them together but I will explain the flaw below:
public IEnumerable<Project> GetHistory<Project, ProjectHistory>(int numberOfChanges)
{
IEnumerable<Project> current;
IEnumerable<Project> history;
current = Session.Query<Project>()
.OrderByDescending(r => r.LastUpdated)
.Take(numberOfChanges);
history = Session.Query<ProjectHistory>()
.OrderByDescending(r => r.LastUpdated).Cast<Project>();
IEnumerable<Project> all = current.Concat(history);
return all.OrderByDescending(r => r.Id).ThenByDescending(r => r.LastUpdated);
}
}
My main issues with the above code are:
The LastUpdated time on the history records are going to reflect the LastUpdated time of the previous Project update so i can't sort desc on that field in the history table and assume i will get a correct descending order of events.
I could use the timestamp field for sorting (as that was the actual time that the record was entered) but it doesn't seem like you can sort on that field using C# nhibernate because that field is just a binary(8) so it translates to a byte[] in C# which doesn't support IComparable.
I can use lastUpdated field on the Project table because sorting by lastupdate field will get me the latest recent events in order. I thought of looping through just the project table and then doing a separate query per each project to grab the latest history project but them this doesn't support a case where multiple changes to the same project id occurred. The issue is i can't figure out a way to get the data in the correct order.
My main point is that I want to accomplish what I think is a pretty generic thing that must be solved already so i must be just missing the basic pattern here.
I already have code that can compare one Project object with another project object and return the field diffs (which works perfect) but I just need a suggestion on figuring out how i get this data out of the database across these tables in the right order (either from my query or code after the fact) so I can show "the last n number of changes" and then use my logic to show the field diff for each of those changes.
Here is my solution for one similar project. Create a view to union project and project history table. Let SQL server to do the heavy lifting.
Here is an example:
CREATE view [dbo].[VwProjectHistory] as select
OtherFieldName,
LastUpdated
from
[dbo].[Project]
union all
select
OtherFieldName,
LastUpdated
from
[dbo].[ProjectHistory]
If I've understood your question correctly you can simply sort on the timestamp converted to long.
// The last row in your question, 0 means start from the start of byte[]
return all.OrderByDescending(r => BitConverter.ToInt64(r.Timestamp,0));
Option 1:
Here's a link that allows you to use the timestamp in an order by clause. I haven't used this myself, so use at your own risk.
Option 2:
Add an auto increment field to ProjectHistory and then you can sort your results by the id of the project and then the auto-increment id. I haven't use the cast operation much, so I'm not sure of those implications, but I'm sure you'll have more work with mapping.
Option 3:
Have you investigated NHibernate Envers, which is a framework for supporting and audit trail? This will be a new learning curve, but it may save you a lot of work in the long run.

Categories