/// <summary> /// <para>Compare two dictionaries (of the same types) and creates SQL inserts /// or updates accordingly.</para> /// <remarks>Second dictionary can be null (only inserts queries will be produced)</remarks> /// <remarks>Use DBTableName and DBFieldName attributes to specify table and field names, in TK</remarks> /// </summary> /// <typeparam name="T">Type of the primary key (uint)</typeparam> /// <param name="storeList">Dictionary retrieved from parser</param> /// <param name="dbList">Dictionary retrieved from DB</param> /// <param name="commentSetter"></param> /// <returns>A string containing full SQL queries</returns> public static string Compare <T>(IEnumerable <Tuple <T, TimeSpan?> > storeList, RowList <T> dbList, Func <T, string> commentSetter) where T : IDataModel, new() { if (!IsTableVisible <T>()) { return(string.Empty); } var fields = GetFields <T>(); if (fields == null) { return(string.Empty); } var rowsIns = new RowList <T>(); var rowsUpd = new Dictionary <Row <T>, RowList <T> >(); var verBuildField = fields.FirstOrDefault(f => f.Item2.Name == "VerifiedBuild"); foreach (var elem1 in storeList) { if (dbList != null && dbList.ContainsKey(elem1.Item1) && !Settings.ForceInsertQueries) // update { if (verBuildField != null) { var buildvSniff = (int)verBuildField.Item2.GetValue(elem1.Item1); var buildvDB = (int)verBuildField.Item2.GetValue(dbList[elem1.Item1].Data); if (buildvDB > buildvSniff) // skip update if DB already has a VerifiedBuild higher than this one { continue; } } var row = new Row <T>(); var elem2 = dbList[elem1.Item1].Data; var fieldUpdateCount = 0; var comment = commentSetter(elem1.Item1); var differingValues = new T(); // we are creating a new object here to always have the same values for non db fields foreach (var field in fields) { var val1 = field.Item2.GetValue(elem1.Item1); var val2 = field.Item2.GetValue(elem2); var attrib = field.Item3.First(); var arr1 = val1 as Array; if (arr1 != null) { var arr2 = (Array)val2; bool arraysEqual = true; var arrayLength = Math.Min(Math.Min(attrib.Count, arr1.Length), arr2.Length); for (var i = 0; i < arrayLength; ++i) { var value1 = arr1.GetValue(i); var value2 = arr2.GetValue(i); if (Utilities.EqualValues(value1, value2)) { arr1.SetValue(null, i); } else { arraysEqual = false; fieldUpdateCount++; } } if (!arraysEqual) { field.Item2.SetValue(differingValues, arr1); } else { field.Item2.SetValue(differingValues, null); // make sure to null default values } continue; } if (!IsFieldEqual(val1, val2, attrib)) { fieldUpdateCount++; field.Item2.SetValue(differingValues, val1); } else { field.Item2.SetValue(differingValues, null); // make sure to null default values } } // no updates required, skip if (fieldUpdateCount == 0) { continue; } // only set comment for rows which arent updating VerifiedBuild only if (fieldUpdateCount != 1 || verBuildField == null || verBuildField.Item2.GetValue(elem1.Item1) == null) { row.Comment = comment; } row.Data = differingValues; if (rowsUpd.TryGetValue(row, out var conditions)) { conditions.Add(elem2); continue; } rowsUpd.Add(row, new RowList <T>().Add(elem2)); } else // insert new { var row = new Row <T> { Comment = commentSetter(elem1.Item1), Data = elem1.Item1 }; rowsIns.Add(row); } } return(new SQLInsert <T>(rowsIns).Build() + Environment.NewLine + new SQLUpdate <T>(rowsUpd).Build()); }
public SQLInsertRow(Row <T> row) { _row = row; }
public Row <T> this[Row <T> key] => this[key.Data];
public SQLUpdateRow(Row <T> value, RowList <T> conditions) { _value = value; WhereClause = new SQLWhere <T>(conditions, true); }
public bool ContainsKey(Row <T> key) { return(ContainsKey(key.Data)); }