private static void AddArray( Dictionary <string, object> @object, IEnumerable <Dictionary <string, object> > arrayElements, string fieldName, InsertIntoArrayComparerKey insertIntoArrayComparerKey = null) { var newArrayKey = GetLeafName(fieldName); Dictionary <string, object> newArrayContainerElement = null; if (insertIntoArrayComparerKey != null) { var existingArrayAttributeName = fieldName.Substring(0, fieldName.Count() - newArrayKey.Count() - 1); var existingArrayContainerElement = GetLeafContainerElement(@object, existingArrayAttributeName); var existingArrayKey = GetLeafName(existingArrayAttributeName); if (!existingArrayContainerElement.ContainsKey(existingArrayKey)) { throw new Exception("The array property, where you are trying to insert the new array, is not a valid property of the primary object. You have to serialize that array first"); } var existingArray = (List <Dictionary <string, dynamic> >)existingArrayContainerElement[existingArrayKey]; if (arrayElements.Any() == false) { existingArrayContainerElement[existingArrayKey] = InsertEmptyArrayIntoExistingArray(existingArray, newArrayKey); return; } var arrayElementsGroupedByArray = arrayElements .GroupBy(x => x[insertIntoArrayComparerKey.NewElementComparerKey]) .ToDictionary(x => x.Key, x => x.Select(y => y.Where(z => z.Key != insertIntoArrayComparerKey.NewElementComparerKey).ToDictionary(z => z.Key, z => z.Value))); foreach (var arrayElementsByArray in arrayElementsGroupedByArray) { var arrayToInsert = arrayElementsByArray.Value; if (!existingArray.Any(x => x[insertIntoArrayComparerKey.ExistingArrayComparerKey].ToString() == arrayElementsByArray.Key.ToString())) { throw new Exception("There is no element in the existing array that matches with the key from the serialized array"); } newArrayContainerElement = existingArray.First(x => x[insertIntoArrayComparerKey.ExistingArrayComparerKey].ToString() == arrayElementsByArray.Key.ToString()); if (!newArrayContainerElement.ContainsKey(newArrayKey)) { newArrayContainerElement.Add(newArrayKey, new Dictionary <string, object>()); } newArrayContainerElement[newArrayKey] = arrayToInsert; } } else { newArrayContainerElement = GetLeafContainerElement(@object, fieldName); newArrayContainerElement[newArrayKey] = arrayElements; } }
/// <summary> /// Serialize an array and insert it into the specified primary object /// </summary> /// <param name="reader">Data Reader</param> /// <param name="results">List of primary objects</param> /// <param name="attributeName">Name of the object belonging to the primary object where the array will be inserted on</param> /// <param name="xmlFields">Array fields that are of type Xml</param> /// <param name="insertIntoArrayComparerKey"> /// If it has value, it will be assumed that the attributeName parameter refers to an array existing within the primary object, /// and the new array will be inserted into it, using this parameter as key to access to each array object and comparing its value with /// the second property of each object in the new array /// </param> /// <returns>List of primary objects with arrays processed and inserted into it</returns> public static Dictionary <object, Dictionary <string, object> > SerializeArray( this SqlDataReader reader, Dictionary <object, Dictionary <string, object> > results, string attributeName, string[] xmlFields = null, InsertIntoArrayComparerKey insertIntoArrayComparerKey = null) { var arrayElements = new Dictionary <object, List <Dictionary <string, object> > >(); var cols = new List <string>(); for (var i = 0; i < reader.FieldCount; i++) { cols.Add(reader.GetName(i)); } while (reader.Read()) { var r = SerializeRow(cols, reader, xmlFields); var key = r.Values.First(); if (!arrayElements.ContainsKey(key)) { arrayElements.Add(key, new List <Dictionary <string, object> >()); } r = r.Skip(1).ToDictionary(x => x.Key, x => x.Value); ((List <Dictionary <string, object> >)arrayElements[key]).Add(r); } //var arrayElements = reader.Serialize(xmlFields) // .Select(x => x.Value) // .GroupBy(x => x.Values.First()) // .ToDictionary(x => x.Key, x => x.Select(y => y.Skip(1).ToDictionary(w => w.Key, w => w.Value)).ToList()); foreach (var @object in results) { if (arrayElements.ContainsKey(@object.Key)) { AddArray(@object.Value, arrayElements[@object.Key], attributeName, insertIntoArrayComparerKey); } else { AddArray(@object.Value, new List <Dictionary <string, object> >(), attributeName, insertIntoArrayComparerKey); } } return(results); }
/// <summary> /// Serialize an object and insert it into the specified primary object /// </summary> public static Dictionary <object, Dictionary <string, object> > SerializeObject( this SqlDataReader reader, Dictionary <object, Dictionary <string, object> > results, string attributeName, InsertIntoArrayComparerKey insertIntoArrayComparerKey = null) { var cols = new List <string>(); for (var i = 0; i < reader.FieldCount; i++) { cols.Add(reader.GetName(i)); } var serializationResults = new Dictionary <object, List <Dictionary <string, object> > >(); while (reader.Read()) { var serializedRow = SerializeRow(cols, reader); var serializationKey = serializedRow.Values.First(); serializedRow = serializedRow.Skip(1).ToDictionary(x => x.Key, x => x.Value); if (!serializationResults.ContainsKey(serializationKey)) { serializationResults.Add(serializationKey, new List <Dictionary <string, object> >()); } serializationResults[serializationKey].Add(serializedRow); } foreach (var @object in results) { if (serializationResults.ContainsKey(@object.Key)) { var serializedNewObject = serializationResults[@object.Key]; var newObjectKey = GetLeafName(attributeName); Dictionary <string, object> newObjectContainerElement = null; if (insertIntoArrayComparerKey != null) { var existingArrayAttributeName = attributeName.Substring(0, attributeName.Count() - newObjectKey.Count() - 1); var existingArrayContainerElement = GetLeafContainerElement(@object.Value, existingArrayAttributeName); var existingArrayKey = GetLeafName(existingArrayAttributeName); if (!existingArrayContainerElement.ContainsKey(existingArrayKey)) { throw new Exception("The array property, where you are trying to insert the new array, is not a valid property of the primary object. You have to serialize that array first"); } var existingArray = (List <Dictionary <string, dynamic> >)existingArrayContainerElement[existingArrayKey]; var serializedNewObjectByArray = serializedNewObject .GroupBy(x => x[insertIntoArrayComparerKey.NewElementComparerKey]) .ToDictionary(x => x.Key, x => x.ToList()); foreach (var serializedNewObjectInArray in serializedNewObjectByArray) { var objectToInsert = SerializeObjectFields(serializedNewObjectInArray.Value); if (!existingArray.Any(x => x[insertIntoArrayComparerKey.ExistingArrayComparerKey].ToString() == serializedNewObjectInArray.Key.ToString())) { throw new Exception("There is no element in the existing array that matches with the key from the serialized dynamic object"); } newObjectContainerElement = existingArray.First(x => x[insertIntoArrayComparerKey.ExistingArrayComparerKey].ToString() == serializedNewObjectInArray.Key.ToString()); if (!newObjectContainerElement.ContainsKey(newObjectKey)) { newObjectContainerElement.Add(newObjectKey, new Dictionary <string, object>()); } newObjectContainerElement[newObjectKey] = objectToInsert; } } else { newObjectContainerElement = GetLeafContainerElement(@object.Value, attributeName); newObjectContainerElement[newObjectKey] = SerializeObjectFields(serializedNewObject); } } } return(results); }