//public void SetData(IEnumerable<string> fieldsToSet, Dictionary<string, Tuple<ISelectQuery, Dictionary<string, string>>> queries, DataRow row) //{ // if (!IsEditable) // { // throw new ReadOnlyException("Cannot call SetData on a read-only Data Object"); // } // SchemaObject schemaObject = Schema.Schema.GetSchemaObject(GetType()); // foreach (IGrouping<string, string> fieldByPath in fieldsToSet.GroupBy(field => // { // if (field.Contains(".")) // { // return field.Substring(0, field.LastIndexOf('.')); // } // return string.Empty; // })) // { // DataObject objectToSetValueOn = this; // if (fieldByPath.Key.Contains(".")) // { // string[] parts = fieldByPath.Key.Split('.'); // SchemaObject lastSchemaObject = schemaObject; // for (int i = 0; i < parts.Length - 1; i++) // { // Relationship relationship = lastSchemaObject.GetRelationship(parts[i]); // if (relationship != null) // { // DataObject relatedDataObject = relationship.GetValue(objectToSetValueOn); // if (relatedDataObject == null) // { // relatedDataObject = (DataObject)Activator.CreateInstance(relationship.RelatedObjectType); // relationship.SetPrivateDataCallback(objectToSetValueOn, relatedDataObject); // } // objectToSetValueOn = relatedDataObject; // lastSchemaObject = relationship.RelatedSchemaObject; // } // else if (lastSchemaObject.GetRelationshipList(parts[i]) != null) // { // break; // } // } // } // string fieldAlias = tableAliasesByFieldPath[fieldByPath.Key]; // foreach (string field in fieldByPath) // { // string fieldName = field; // if (fieldName.Contains('.')) // { // fieldName = fieldName.Substring(fieldName.LastIndexOf('.') + 1); // } // string columnName = $"{fieldAlias}_{fieldName}"; // object databaseValue = row[columnName]; // databaseValue = databaseValue == DBNull.Value ? null : databaseValue; // Schema.Field schemaField = schemaObject.GetField(field); // schemaField.SetPrivateDataCallback(objectToSetValueOn, databaseValue); // } // } //} public void SetData(IEnumerable <string> fieldsToSet, Dictionary <string, Tuple <ISelectQuery, Dictionary <string, string> > > queries, DataRow outerObjectRow) { IEnumerable <string> fieldsWeCanDoSomethingAbout = fieldsToSet.Where(field => !queries.Keys.Where(k => !string.IsNullOrEmpty(k)).Any(reverseFieldPath => field.StartsWith(reverseFieldPath))); IEnumerable <IGrouping <string, string> > fieldsByFieldPath = fieldsWeCanDoSomethingAbout.OrderBy(field => field).GroupBy(field => field.Contains('.') ? field.Substring(0, field.LastIndexOf('.')) : ""); // Load in all parent relationships foreach (IGrouping <string, string> fieldGroup in fieldsByFieldPath.Where(group => !string.IsNullOrEmpty(group.Key))) { SchemaObject currentSchemaObject = Schema.Schema.GetSchemaObject(GetType()); DataObject currentObject = this; string[] fieldPathParts = fieldGroup.Key.Split('.'); for (int i = 0; i < fieldPathParts.Length; i++) { Relationship relationship = currentSchemaObject.GetRelationship(fieldPathParts[i]); DataObject relatedObject = relationship.GetValue(this); if (relatedObject == null) { relatedObject = (DataObject)Activator.CreateInstance(relationship.RelatedObjectType); relatedObject.isEditable = false; relationship.SetPrivateDataCallback(currentObject, relatedObject); } currentSchemaObject = relationship.RelatedSchemaObject; currentObject = relatedObject; } } Dictionary <string, string> tableAliasesForOuterRow = queries[""].Item2; // Set data on this object or parent objects foreach (IGrouping <string, string> fieldGroup in fieldsByFieldPath) { string tableAlias = tableAliasesForOuterRow[fieldGroup.Key]; DataObject dataObjectToSet = this; SchemaObject schemaObjectToSet = Schema.Schema.GetSchemaObject(GetType()); if (!string.IsNullOrEmpty(fieldGroup.Key)) { string[] fieldPathParts = fieldGroup.Key.Split('.'); for (int i = 0; i < fieldPathParts.Length; i++) { Relationship relationship = schemaObjectToSet.GetRelationship(fieldPathParts[i]); dataObjectToSet = relationship.GetValue(dataObjectToSet); schemaObjectToSet = Schema.Schema.GetSchemaObject(dataObjectToSet.GetType()); } } foreach (string field in fieldGroup) { string fieldToSet = field; if (fieldToSet.Contains('.')) { fieldToSet = fieldToSet.Substring(fieldToSet.LastIndexOf('.') + 1); } object value = outerObjectRow[$"{tableAlias}_{fieldToSet}"]; Schema.Field schemaField = schemaObjectToSet.GetField(fieldToSet); schemaField.SetPrivateDataCallback(dataObjectToSet, value); } } // Set data for reverse relationships HashSet <string> handledReverseRelationships = new HashSet <string>(); foreach (string reverseRelationship in queries.Keys.Where(key => !string.IsNullOrEmpty(key))) { string[] reverseRelationshipParts = reverseRelationship.Split('.'); DataObject parentObject = this; SchemaObject parentSchemaObject = Schema.Schema.GetSchemaObject(GetType()); string reverseRelationshipWeCanDoSomethingAbout = ""; RelationshipList relationshipList = null; for (int i = 0; i < reverseRelationshipParts.Length; i++) { Relationship relationship = parentSchemaObject.GetRelationship(reverseRelationshipParts[i]); if (relationship != null) { parentObject = relationship.GetValue(parentObject); parentSchemaObject = relationship.RelatedSchemaObject; reverseRelationshipWeCanDoSomethingAbout += relationship.RelatedSchemaObject.ObjectName + "."; } else { relationshipList = parentSchemaObject.GetRelationshipList(reverseRelationshipParts[i]); reverseRelationshipWeCanDoSomethingAbout += relationshipList.RelationshipListName + "."; break; } } if (!handledReverseRelationships.Add(reverseRelationshipWeCanDoSomethingAbout)) { continue; } long? primaryKey = parentObject.PrimaryKeyField.GetValue(parentObject) as long?; ISelectQuery query = queries[reverseRelationshipWeCanDoSomethingAbout].Item1; Condition primaryKeyCondition = new Condition() { Left = (Base.Data.Operand.Field)relationshipList.ForeignKeyName, ConditionType = Condition.ConditionTypes.Equal, Right = new Literal(primaryKey) }; ICondition previousQueryCondition = query.WhereCondition; if (query.WhereCondition != null) { ConditionGroup conditionGroup = new ConditionGroup() { ConditionGroupType = ConditionGroup.ConditionGroupTypes.And, Conditions = new List <ICondition>() { query.WhereCondition, primaryKeyCondition } }; query.WhereCondition = conditionGroup; } else { query.WhereCondition = primaryKeyCondition; } HashSet <string> childFieldsToSet = fieldsToSet.Where(f => f.StartsWith(reverseRelationshipWeCanDoSomethingAbout)).Select(f => f.Replace(reverseRelationshipWeCanDoSomethingAbout, "")).ToHashSet(); childFieldsToSet.Add(relationshipList.RelatedSchemaObject.PrimaryKeyField.FieldName); Dictionary <string, Tuple <ISelectQuery, Dictionary <string, string> > > childQueries = new Dictionary <string, Tuple <ISelectQuery, Dictionary <string, string> > >(); foreach (KeyValuePair <string, Tuple <ISelectQuery, Dictionary <string, string> > > childQuery in queries.Where(kvp => kvp.Key.StartsWith(reverseRelationshipWeCanDoSomethingAbout))) { childQueries.Add(childQuery.Key.Replace(reverseRelationshipWeCanDoSomethingAbout, ""), childQuery.Value); } object reverseRelationshipList = relationshipList.GetPrivateDataCallback(parentObject); MethodInfo addMethod = reverseRelationshipList.GetType().GetMethod("Add", new Type[] { relationshipList.RelatedObjectType }); DataTable results = query.Execute(null); query.WhereCondition = previousQueryCondition; foreach (DataRow row in results.Rows) { DataObject childObject = (DataObject)Activator.CreateInstance(relationshipList.RelatedObjectType); childObject.isEditable = false; childObject.SetData(childFieldsToSet, childQueries, row); addMethod.Invoke(reverseRelationshipList, new object[] { childObject }); } parentObject.retrievedPaths.Add(relationshipList.RelationshipListName); } }
public static DataObject GetEditableByPrimaryKey(Type dataObjectType, long?primaryKey, ITransaction transaction, IEnumerable <string> readOnlyFields) { DataObject dataObject = (DataObject)Activator.CreateInstance(dataObjectType); dataObject.isInsert = false; SchemaObject schemaObject = Schema.Schema.GetSchemaObject(dataObjectType); int tableAliasCounter = 1; Dictionary <string, string> tableAliasesByFieldPath = new Dictionary <string, string>() { { "", "table000" } }; ISelectQuery selectQuery = SQLProviderFactory.GetSelectQuery(); foreach (Schema.Field field in schemaObject.GetFields()) { Select select = new Select() { SelectOperand = (Base.Data.Operand.Field) $"table000.{field.FieldName}", Alias = $"table000_{field.FieldName}" }; selectQuery.SelectList.Add(select); } IOrderedEnumerable <string> sortedFields = readOnlyFields.Where(f => f.Contains('.')).OrderBy(f => f); foreach (string readOnlyField in sortedFields) { string[] parts = readOnlyField.Split('.'); string checkedPath = ""; DataObject lastDataObject = dataObject; SchemaObject lastSchemaObject = schemaObject; for (int i = 0; i < parts.Length - 1; i++) { string myAlias = tableAliasesByFieldPath[checkedPath]; if (!string.IsNullOrEmpty(checkedPath)) { checkedPath += "."; } checkedPath += parts[i]; if (tableAliasesByFieldPath.ContainsKey(checkedPath)) { continue; } tableAliasCounter++; string newAlias = $"table{tableAliasCounter.ToString("D3")}"; tableAliasesByFieldPath.Add(checkedPath, newAlias); Relationship relationship = lastSchemaObject.GetRelationship(parts[i]); DataObject relatedDataObject = relationship.GetValue(lastDataObject); if (relatedDataObject == null) { relatedDataObject = (DataObject)Activator.CreateInstance(relationship.RelatedObjectType); relatedDataObject.isEditable = false; relationship.SetPrivateDataCallback(lastDataObject, relatedDataObject); } Join join = new Join(); join.JoinType = Join.JoinTypes.Left; join.Table = new Table(relationship.RelatedSchemaObject.SchemaName, relationship.RelatedSchemaObject.ObjectName, newAlias); join.Condition = lastDataObject.GetRelationshipCondition(relationship, myAlias, newAlias); selectQuery.JoinList.Add(join); lastDataObject = relatedDataObject; lastSchemaObject = relationship.RelatedSchemaObject; } string path = readOnlyField.Substring(0, readOnlyField.LastIndexOf('.')); string pathField = readOnlyField.Substring(readOnlyField.LastIndexOf('.') + 1); string finalAlias = tableAliasesByFieldPath[path]; Select readOnlySelect = new Select() { SelectOperand = (Base.Data.Operand.Field) $"{path}.{pathField}", Alias = $"{path}_{pathField}" }; selectQuery.SelectList.Add(readOnlySelect); } selectQuery.WhereCondition = new Condition() { Left = (Base.Data.Operand.Field) $"table000_{schemaObject.PrimaryKeyField.FieldName}", ConditionType = Condition.ConditionTypes.Equal, Right = new Literal(primaryKey) }; DataTable dataTable = selectQuery.Execute(transaction); if (dataTable.Rows.Count <= 0) { return(null); } DataRow row = dataTable.Rows[0]; foreach (Schema.Field field in schemaObject.GetFields()) { object value = row[$"table000_{field.FieldName}"]; field.SetPrivateDataCallback(dataObject, value); dataObject.retrievedPaths.Add(field.FieldName); } foreach (string readOnlyField in sortedFields) { string path = readOnlyField.Substring(0, readOnlyField.LastIndexOf('.')); string pathField = readOnlyField.Substring(readOnlyField.LastIndexOf('.') + 1); string alias = tableAliasesByFieldPath[path]; object value = row[$"{alias}_{pathField}"]; DataObject lastObject = dataObject; SchemaObject lastSchemaObject = schemaObject; string[] parts = path.Split('.'); for (int i = 0; i < parts.Length; i++) { lastObject.retrievedPaths.Add(parts[i]); Relationship relationship = lastSchemaObject.GetRelationship(parts[i]); lastObject = relationship.GetValue(lastObject); lastSchemaObject = relationship.RelatedSchemaObject; } Schema.Field field = lastSchemaObject.GetField(pathField); field.SetPrivateDataCallback(lastObject, value); lastObject.retrievedPaths.Add(pathField); } return(dataObject); }