Beware DEX_ROW_TS for data synchronisation

DEX_ROW_TS is a SQL server database field. It is found on some tables in Dynamics GP ERP system(since V10). The field contains a UTC timestamp that is “stamped” whenever that row in the database is changed, setting it to current time and date. A blog entry from David Musgrave, Understanding how Microsoft Dynamics GP works with Microsoft SQL Server, says that this was introduced to “help with Business Data Catalog (BDC) indexing for SharePoint searches”.

Run this script from Tim Foster, to see all the tables in the GP database that use it;

SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name LIKE '%DEX_ROW_TS%'
ORDER BY schema_name, table_name;
 
Executing this script yields the following tables from using a test GP2010 database (including the DYNAMICS & Company database):
 
Figure: Tables containing DEX_ROW_TS
MC40200 GL00100 IV00101 PM00200 POP10100 RM00101 SOP10100 SY01200
  GL10000 IV00107 PM00300 POP10110 RM00102 SOP10200 UPR00100
  GL12000 IV00108 PM10000 POP30100 RM00301 SOP30200  
  GL20000 IV10000 PM20000 POP30110 RM00303 SOP30300  
  GL30000 IV30200 PM30200   RM10301    
  GL32000 IV40201     RM20101    
    IV40202     RM30101    
    IV40800          

A database trigger is responsible for keeping the timestamp updated on changes. Below you can see the trigger that works against the table MC40200.
CREATE TRIGGER [dbo].[zDT_MC40200U] 
ON [dbo].[MC40200]
AFTER UPDATE
AS
set nocount on
BEGIN
UPDATE dbo.MC40200
SET DEX_ROW_TS = GETUTCDATE()
FROM dbo.MC40200,
inserted
WHERE MC40200.CURNCYID = inserted.CURNCYID
END set
nocount off

As can be seen from the script above, the timestamp is updated with the current server UTC time when a row insert occurs. There are similar triggers for updates to the rows. The time used is the time of the SQL server, set by using the TSQL function GETUTCDATE(). It is worth noting that this date time is with no time zone offsets. It is easy to write SQL scripts that may break due to local time zones, remember to take this into account.

Using DEX_ROW_TS for data synchronisation

If the need arises to keep the Dynamics GP data replicated to a CRM system or say an ecommerce website in Azure, perhaps a data warehouse, then the field becomes very useful. The value of DEX_ROW_TS since the last sync can be compared checked across all the tables and allow the selection of only the rows that have changed and thus only those rows may be selected for sync or push to The Cloud.

Don’t get too excited, I’m about to put the fly in the ointment. Using the field DEX_ROW_TS is very useful, but there are issues with relying on it too much…

Only some tables have the DEX_ROW_TS column on them

It soon becomes apparent that the field DEX_ROW_TS is not ubiquitous over all tables (as was seen from the results of the earlier database query). Although it exists on many of the common tables used in integrations, it is also lacking from so many others. Unfortunately once it is not on one table that requires synchronisation, then a another solution needs to be sought for identifying changed rows.

Table IV00105, used in price list setup is an example of a table lacking the column.

image

Perhaps it is possible to infer the need to re-sync a record in some cases, from the change in a related record in a table that does contain the timestamp however treading down this route means introducing a lot of logic and database work for each update.

Tables can update the time stamp on different table, even if it didn’t change

YES, that is correct, the time stamp can lie! Tables such as Item Master are updated by any change in the Item Quantity table for the same item!

By scripting out the tables and looking at the triggers, it is found that six tables have cross table updates of this nature. A operation on a row in these tables will update its own time stamp, but also crucially it will update the timestamp of another table too, even if nothing has changed in that other table’s row!

All the occurrences where there are interdependencies between updates in one table and update of DEX_ROW_TS column updates in another table are illustrated below. All of these are in the company database, none are in the DYNAMICS database.

Table Source of Trigger Trig Type Time Stamp Updated In Table
[IV00102] – Item Quantity Master INSERT IV00101 – Item Master
[IV00102] – Item Quantity Master DELETE IV00101 – Item Master
[IV00102] – Item Quantity Master UPDATE IV00101 – Item Master
[IV00104] – Item Kit Master INSERT IV00101 – Item Master
[IV00104] – Item Kit Master UPDATE IV00101 – Item Master
[IV00104] – Item Kit Master DELETE IV00101 – Item Master
[IV00107] – Item Price List Options UPDATE IV40800 - Price Level Setup
[IV00108] – Item Price List INSERT IV40800 - Price Level Setup
[IV00108] – Item Price List INSERT IV00107 – Item Price List Options
[IV00108] – Item Price List DELETE IV40800 - Price Level Setup
[IV00108] – Item Price List DELETE IV00107 – Item Price List Options
[IV00108] – Item Price List UPDATE IV40800 - Price Level Setup
[IV00108] – Item Price List UPDATE IV00107 – Item Price List Options
[IV40202] – U of M Schedule Detail Setup INSERT IV40201 – U of M Schedule Setup (header)
[IV40202] – U of M Schedule Detail Setup DELETE IV40201 – U of M Schedule Setup (header)
[IV40202] – U of M Schedule Detail Setup UPDATE IV40201 – U of M Schedule Setup (header)
[RM00102] - Customer Master Address File INSERT RM00101 - RM Customer Master
[RM00102] - Customer Master Address File DELETE RM00101 - RM Customer Master
[RM00102] - Customer Master Address File UPDATE RM00101 - RM Customer Master

 

Be aware it is not just synchronisation where this can be an issue. Perhaps there are SQL jobs sending reports when rows have been changed, in the customer set up records. These could be wrong due to corruption from changed addresses in the address table.

SQL Server Change Tracking

If you use SQL server change tracking, then you may also experience the same misleading update. Obviously the cross table update would be logged as an update to both tables by SQL server change tracking. At least it is possible to query for the columns updated by using a column bitmask with change tracking.

Customer Created Custom SQL Triggers

A blog post by Milan of Merit Solutions highlights another danger that is introduced by the triggers of the DEX_ROW_TS , read it here Dynamics GP Workflow Tips for DEX_ROW_TS.

Essentially be careful that triggers may run twice as the triggers that keep the time stamp updated are operating on the same table that triggered the trigger (follow me?), a loop could be accidentally caused. The blog proposes the use of (NOT UPDATE (DEX_ROW_TS)) and sp_settriggerorder  to prevent this happening and manage the trigger order, if required.

Implementing the Microsoft Dynamics GP Web Client–Book Review

Implementing the Microsoft Dynamics GP Web ClientERP systems are migrating to the near zero deployment of web browser delivery and consumption. With Microsoft’s release of the GP Web Client, Dynamics GP is now no exception. Ian Grieve has produced a book that brings lucidity to the process of installing and configuring the GP Web Client and server.

Ian is a figure well known in the Dynamics GP community and has been recognised as such by the awarding of Microsoft MVP (Most Valuable Professional) status. In this book Ian imparts his wealth of experience and disseminates the knowledge he has brought back from the field, where he is working as a busy Dynamics consultant. In his role he has been exposed to an assortment of company requirements and environments that has helped shape this book.

I read the book whilst preparing for my first web deployment. I was grateful for the help with the daunting, multifaceted nature of a Dynamics GP Web Client and server install. The book is excellent for the impatient or time pressed professional needing to get up to speed quickly with this new member of the Dynamics GP system. The pages provide a well-lit path through the process of getting to a functional GP Web Client and server install, quickly and without having to wade though manuals and online guides.

The structure of Ian’s book breaks the system down, addressing each part separately, in a step by step manner. It is rich in supporting screen shots, providing continuous reassurance at each step, feeling much like a colleague has provided you with a much toiled over build script. Although it is valuable to the configuration and installation of the GP Web Client, the book may also facilitate

in comprehending an overview of the install for system administrators too.

Subjects covered also include those important to the end user such as integration with Microsoft Office applications and SQL Server Reporting Services through Silverlight. The limitations of the Web Client are also covered together security set ups. I must praise the inclusion of a troubleshooting section, inevitably needed in any complex server system for configuration and on-going reference.

Dynamics GP is a little sparse in supporting professional grade technical literature, it is good that Ian has written this solid guide to help address that shortage.

Review by T.Wappat

Buy Implementing the Microsoft Dynamics GP Web Client by Ian Grieve

Ian Grieve

Team Foundation Server (TFS) -The underlying connection was closed

image
Having build and upgraded Team Foundation server from 2010 to 2013, SQL Sever and Sharpoint Foundation 2013, running on VMWare ESX,  the team found very frequent and random like connection dropped problems, most frequent being:
  • connection that was expected to be kept alive was closed
  • The underlying connection was closed

This happened trying to check things in, or other source tracking related activities against Team Foundation Server.

The hunt was on the the cause, a week of investigation (on and off), heading off looking at the IIS settings, checking settings for WCF, looking for possible max connection limits, working pools and recycling logs etc.

Also investigated a post regarding network interface card (NIC) off loading and to switch it off on virtual boxes (I’m not convinced by that).

Solution

For others in a similar position, I present our solution, the static IP address that was assigned to the server had accidentally had a a printer assigned to it too. So whenever the user came in to work and put the printer on (not every day), we would experience these problems, for a bit, until the printer went off again. All due to the duplicate IP address.

How to make GP company login text boxes longer

In the blog post series by David Musgrave, he shows how to customise the GP company login boxes, to make them long enough to see very long company names in full. David uses Dexterity in the third part of the series. However in the latest he attempts to do the same using an addin, albeit he “cheats” by passing in the SanScript. Note this is not a supported method.
By using the Continuum COM library to allow .NET code in the Dynamics GP Visual Studio addin to pass SanScript through to the GP we CAN do it, see how I did it!

The original article can be found here:

image

Customising the Company Login window series Part 4 - Visual Studio Toolsby David Musgrave

So David had a problem getting it working, I had Visual Studio open on my Addin project, so I gave it a go.

Make a reference to the Continuum

This is a COM object in, so go to your project reference and search for “contin” and then add the reference. Ensure you marry the version number with the version of GP you are using.

image

Store the script in a project resource

Under the project settings, you can store resources. This is a good place to put your scripts as it deals with line feeds and keeps them in an intact form for future editing.

Go to the resources tab of the project properties, create a new resource and paste in the script provided by David. We are going to use the .NET code to run the script, so we don’t need to put it in a procedure, only take the fragment that does the deed. Name the resource LoginResizeScript

image

Add event handler

Now when the company login window is opened we want to execute the script to resize the text boxes on that window. So to me it seems like a good plan to add and event handler to the company switch form. Now go to your GPAddin.vb and add and event handler like this for the company switch form.

Sub Initialize() Implements IDexterityAddIn.Initialize
'You should add code to only execute once in lifetime
AddHandler Microsoft.Dexterity.Applications.DynamicsDictionary.OpenSwitchCompanyFormProcedure._Instance.InvokeAfterOriginal, AddressOf DoLoginResize

End Sub

Deal with the namespaces

Important as the project reference messes you up!

Imports DynamicsGP = Microsoft.Dexterity.Applications.Dynamics

Execute the script

So next the script needs to run in response to the event firing on the Switch Company event handler. Add the following to your GPAddin.vb .

The SanScript is now held in a project resource we can reference by My.Resources.Resources.LoginResizeScript so we push this into the ExecuteSanscript method.

Public Sub DoLoginResize(sender As Object, e As EventArgs)
Dim CompilerApp As New Dynamics.Application
Dim CompilerMessage As String = Nothing
Dim CompilerError As Integer
' Execute SanScript in Dynamics GP
CompilerError = CompilerApp.ExecuteSanscript(My.Resources.Resources.LoginResizeScript, CompilerMessage)
If CompilerError <> 0 Then
Windows.Forms.MessageBox.Show(CompilerMessage)
End If
End Sub

Resulting resized controls – it works!

image

And hey it works from VB.NET too! I love Visual Studio and Dynamics GP!