Пример #1
0
        //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);
            }
        }