コード例 #1
0
        /// <summary>
        /// Given a parent and child, this method creates the SQL statement needed to update tables and make both current
        /// and in sync with each other.
        /// </summary>
        /// <param name="tableMap">Map defining the From-To column combination</param>
        /// <param name="parentColumns">List of parent Columns and pertinent values</param>
        /// <param name="childColumns">List of child Columns and pertinent values</param>
        /// <param name="guid">The unique link that's equal between parent and child</param>
        /// <param name="tableToUpdate">Table that we're going to update</param>
        /// <param name="version">The highest RowVersion we're going to update table with</param>
        /// <param name="conn">Connetion to target table</param>
        /// <returns>Returns string with the update SQL statement</returns>
        private static string UpdateSqlCmd(TableMap tableMap, List <DataColumn> parentColumns, List <DataColumn> childColumns, Guid guid, string tableToUpdate, long version, SqlConnection conn)
        {
            var setCmd = "";

            //For each column, get both values and compare to each other.  If ANY are different, add to setCmd
            parentColumns.ForEach(parentColumn =>
            {
                var parentName  = parentColumn.Name;
                var parentValue = parentColumn.Value;
                childColumns.ForEach(childColumn =>
                {
                    var childName  = childColumn.Name;
                    var childValue = childColumn.Value;

                    //Names of columns may be different so get name based on map
                    var parentColumnMap   = tableMap.ColumnMaps.FirstOrDefault(p => p.FromColumn.Name == parentName);
                    var childColumnMap    = tableMap.ColumnMaps.FirstOrDefault(p => p.ToColumn.Name == parentName);
                    var mappedName        = "";
                    var isAutoIncremented = false;
                    var isKey             = false;

                    //If parentColumnMap != null it's a parent-to-Child scenario, else it's child-to-parent
                    if (parentColumnMap != null)
                    {
                        mappedName        = parentColumnMap.ToColumn.Name;
                        isAutoIncremented = parentColumnMap.ToColumn.IsAutoNumber;
                        isKey             = parentColumnMap.ToColumn.IsKey;
                    }
                    else if (childColumnMap != null)
                    {
                        mappedName        = childColumnMap.FromColumn.Name;
                        isAutoIncremented = childColumnMap.FromColumn.IsAutoNumber;
                        isKey             = childColumnMap.FromColumn.IsKey;
                    }

                    //If it's not auto-incremented and not column RowVersion (added later), include as part of set.
                    if (!isAutoIncremented && !childName.Equals("RowVersion"))
                    {
                        //If the column names are the same and the values are different we should update that field.
                        if (childName.Equals(mappedName) && !childValue.Equals(parentValue))
                        {
                            var type  = childColumn.ColumnType;
                            var value = (type == typeof(int) || type == typeof(long) ? parentValue : "'" + parentValue + "'");

                            //If it's a primary columnName, find a unique value if neccessary
                            if (isKey)
                            {
                                value = GenerateUniqueKey(conn, tableToUpdate, mappedName, parentValue.ToString(), type);
                            }

                            //Add all else to set
                            setCmd += childName + "=" + value + ", ";
                        }
                    }
                });
            });

            return($@"UPDATE {tableToUpdate} 
                      SET {setCmd} RowVersion = {version}
                      WHERE RowGuid='{guid}'");
        }
コード例 #2
0
        /// <summary>
        /// Syncs both tables together after verifying which table has greater RowVersion or insert if missing
        /// </summary>
        /// <param name="tableMap">Map defining the From-To column combination</param>
        /// <param name="childConn">Open child connection</param>
        /// <param name="parentConn">Open parent connection</param>
        /// <param name="childTable">Name of Child table</param>
        /// <param name="parentTable">Name of Parent table</param>
        /// <param name="diff">Dictionary with Unique Guid's as columnName and List parent/child rows as value</param>
        private static void SyncTables(TableMap tableMap, SqlConnection childConn, SqlConnection parentConn, string childTable, string parentTable, Dictionary <Guid, ParentChild> diff)
        {
            //For each difference found process it
            foreach (var entry in diff)
            {
                //Get the row versions
                var parentChild = entry.Value;
                var parentRow   = parentChild.Parent.Columns.FirstOrDefault(c => c.Name.Equals("RowVersion"));
                var childRow    = parentChild.Child.Columns.FirstOrDefault(c => c.Name.Equals("RowVersion"));

                //If it's equal to null, return 0 else return the value.
                //This is a sanity check as it should never be null.
                var parentRowVersion = (long?)parentRow?.Value ?? 0;
                var childRowVersion  = (long?)childRow?.Value ?? 0;

                string cmd;
                var    sqlCmd = new SqlCommand();

                //If row version is 0, we didn't have a match so an insert needs to happen
                if (parentRowVersion == 0 || childRowVersion == 0)
                {
                    if (parentRowVersion != 0)
                    {
                        //We found a parent that didn't have a matching child.
                        SyncReport += $"GUID: {entry.Key} has an entry in table {parentTable} but not in {childTable}" + " \n";
                        if (!isReportOnly)
                        {
                            var fromColumns = parentChild.Parent.Columns;
                            cmd = InsertSqlCmd(tableMap, fromColumns, childTable, childConn);

                            //Insert into child
                            sqlCmd = new SqlCommand(cmd, childConn);
                        }
                    }
                    else
                    {
                        //We found a child that didn't have a matching parent.
                        SyncReport += $"GUID: {entry.Key} has an entry in table {childTable} but not in {parentTable}" + " \n";
                        if (!isReportOnly)
                        {
                            var fromColumns = parentChild.Child.Columns;
                            cmd = InsertSqlCmd(tableMap, fromColumns, parentTable, parentConn);

                            //Insert into parent
                            sqlCmd = new SqlCommand(cmd, parentConn);
                        }
                    }
                }
                else
                {
                    //Check for different rowVersions between parent and child and update
                    if (parentRowVersion > childRowVersion)
                    {
                        //Parent is more up-to-date, update child
                        SyncReport += $@"GUID: {entry.Key} has a higher RowVersion of {parentRowVersion} in {parentTable} compared to {childRowVersion} in {childTable}" + " \n";
                        if (!isReportOnly)
                        {
                            var fromColumns = parentChild.Parent.Columns;
                            var toColumns   = parentChild.Child.Columns;
                            cmd = UpdateSqlCmd(tableMap, fromColumns, toColumns, entry.Key, childTable, parentRowVersion, childConn);

                            //Update the child
                            sqlCmd = new SqlCommand(cmd, childConn);
                        }
                    }
                    else
                    {
                        //Child is more up-to-date, update parent
                        SyncReport += $@"GUID: {entry.Key} has a higher RowVersion of {childRowVersion} in {childTable} compared to {parentRowVersion} in {parentTable}" + " \n";
                        if (!isReportOnly)
                        {
                            var fromColumns = parentChild.Child.Columns;
                            var toColumns   = parentChild.Parent.Columns;
                            cmd = UpdateSqlCmd(tableMap, fromColumns, toColumns, entry.Key, parentTable, childRowVersion, parentConn);

                            //Update the parent
                            sqlCmd = new SqlCommand(cmd, parentConn);
                        }
                    }
                }

                if (!isReportOnly)
                {
                    sqlCmd.ExecuteNonQuery();
                    SyncReport += "Differences were remedied \n";
                }
            }
        }