예제 #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);
            }
        }
예제 #2
0
파일: Search.cs 프로젝트: CSX8600/MCSync
        private Dictionary <string, Tuple <ISelectQuery, Dictionary <string, string> > > GetBaseQueries(SchemaObject thisSchemaObject, HashSet <string> fields, string upperFieldPath = null)
        {
            Dictionary <string, Tuple <ISelectQuery, Dictionary <string, string> > > queriesByFieldPath = new Dictionary <string, Tuple <ISelectQuery, Dictionary <string, string> > >();

            DataObject dataObject = (DataObject)Activator.CreateInstance(thisSchemaObject.DataObjectType);

            fields.Add(thisSchemaObject.PrimaryKeyField.FieldName);

            IEnumerable <string> sortedFields = fields.Where(f => !f.Contains(".")).Concat(fields.Where(f => f.Contains(".")).OrderBy(str => str));

            Dictionary <string, string> tableAliasesByFieldPath = new Dictionary <string, string>()
            {
                { "", "table000" }
            };
            int tableAliasCounter = 1;

            List <Join> joinList = new List <Join>();

            foreach (string fieldPath in sortedFields.Where(f => f.Contains(".")).Select(f => f.Substring(0, f.LastIndexOf("."))))
            {
                string[] fieldPathParts = fieldPath.Split('.');

                string       checkedFieldPath = "";
                DataObject   lastObject       = dataObject;
                SchemaObject lastSchemaObject = thisSchemaObject;
                for (int i = 0; i < fieldPathParts.Length; i++)
                {
                    string myAlias = tableAliasesByFieldPath[checkedFieldPath];

                    if (!string.IsNullOrEmpty(checkedFieldPath))
                    {
                        checkedFieldPath += ".";
                    }

                    checkedFieldPath += fieldPathParts[i];

                    RelationshipList relationshipList = lastSchemaObject.GetRelationshipList(fieldPathParts[i]);
                    if (relationshipList != null)
                    {
                        if (queriesByFieldPath.ContainsKey(checkedFieldPath + "."))
                        {
                            break;
                        }

                        HashSet <string> fieldsAfterReverseRelationship = sortedFields.Where(field => field.StartsWith(checkedFieldPath + ".")).Select(f => f.Replace(checkedFieldPath + ".", "")).ToHashSet();
                        fieldsAfterReverseRelationship.Add(relationshipList.RelatedSchemaObject.PrimaryKeyField.FieldName);

                        foreach (KeyValuePair <string, Tuple <ISelectQuery, Dictionary <string, string> > > kvp in GetBaseQueries(relationshipList.RelatedSchemaObject, fieldsAfterReverseRelationship, (upperFieldPath ?? "") + checkedFieldPath + "."))
                        {
                            queriesByFieldPath.Add(checkedFieldPath + "." + kvp.Key, kvp.Value);
                        }

                        break;
                    }

                    Relationship relationship        = lastSchemaObject.GetRelationship(fieldPathParts[i]);
                    SchemaObject relatedSchemaObject = relationship.RelatedSchemaObject;
                    DataObject   relatedDataObject   = (DataObject)Activator.CreateInstance(relatedSchemaObject.DataObjectType);

                    if (tableAliasesByFieldPath.ContainsKey(checkedFieldPath))
                    {
                        lastObject       = relatedDataObject;
                        lastSchemaObject = relatedSchemaObject;

                        continue;
                    }

                    fields.Add(checkedFieldPath + "." + relatedSchemaObject.PrimaryKeyField.FieldName);

                    tableAliasCounter++;
                    string otherAlias = $"table{tableAliasCounter.ToString("D3")}";
                    tableAliasesByFieldPath.Add(checkedFieldPath, otherAlias);

                    Join join = new Join();
                    join.Table     = new Table(relatedSchemaObject.SchemaName, relatedSchemaObject.ObjectName, otherAlias);
                    join.JoinType  = Join.JoinTypes.Left;
                    join.Condition = lastObject.GetRelationshipCondition(relationship, myAlias, otherAlias);
                    joinList.Add(join);

                    lastObject       = relatedDataObject;
                    lastSchemaObject = relatedSchemaObject;
                }
            }

            if (SearchCondition != null)
            {
                foreach (string conditionFieldPath in SearchCondition.GetFieldPaths())
                {
                    if (string.IsNullOrEmpty(conditionFieldPath))
                    {
                        continue;
                    }

                    string workingConditionFieldPath = conditionFieldPath + ".";
                    if (!string.IsNullOrEmpty(upperFieldPath))
                    {
                        if (!workingConditionFieldPath.StartsWith(upperFieldPath))
                        {
                            continue;
                        }

                        workingConditionFieldPath = workingConditionFieldPath.Replace(upperFieldPath, "");
                    }

                    if (tableAliasesByFieldPath.ContainsKey(workingConditionFieldPath))
                    {
                        continue;
                    }

                    string[]     parts            = workingConditionFieldPath.Split('.');
                    DataObject   lastObject       = dataObject;
                    SchemaObject lastSchemaObject = thisSchemaObject;
                    string       workingPath      = "";
                    foreach (string part in parts)
                    {
                        if (string.IsNullOrEmpty(part))
                        {
                            continue;
                        }

                        string myAlias = tableAliasesByFieldPath[workingPath];

                        if (!string.IsNullOrEmpty(workingPath))
                        {
                            workingPath += ".";
                        }

                        workingPath += part;

                        RelationshipList relationshipList = lastSchemaObject.GetRelationshipList(part);
                        if (relationshipList != null)
                        {
                            break; // This will happen later
                        }

                        Relationship relationship  = lastSchemaObject.GetRelationship(part);
                        DataObject   relatedObject = relationship.GetValue(lastObject);

                        if (relatedObject == null)
                        {
                            relatedObject = (DataObject)Activator.CreateInstance(relationship.RelatedObjectType);
                        }

                        lastSchemaObject = relationship.RelatedSchemaObject;

                        if (tableAliasesByFieldPath.ContainsKey(workingPath))
                        {
                            lastObject = relatedObject;
                            continue;
                        }

                        string newAlias = $"table{tableAliasCounter.ToString("D3")}";
                        tableAliasCounter++;

                        Join join = new Join();
                        join.JoinType  = Join.JoinTypes.Left;
                        join.Table     = new Table(lastSchemaObject.SchemaName, lastSchemaObject.ObjectName, newAlias);
                        join.Condition = lastObject.GetRelationshipCondition(relationship, myAlias, newAlias);
                        joinList.Add(join);

                        lastObject = relatedObject;

                        tableAliasesByFieldPath[workingPath] = newAlias;
                    }
                }
            }

            ISelectQuery selectQuery = SQLProviderFactory.GetSelectQuery();

            selectQuery.Table    = new Table(thisSchemaObject.SchemaName, thisSchemaObject.ObjectName, "table000");
            selectQuery.JoinList = joinList;

            foreach (string field in sortedFields.Where(f => !queriesByFieldPath.Keys.Any(fp => f.StartsWith(fp))))
            {
                string path      = "";
                string fieldName = "";
                if (field.Contains('.'))
                {
                    path      = field.Substring(0, field.LastIndexOf('.'));
                    fieldName = field.Substring(field.LastIndexOf('.') + 1);
                }
                else
                {
                    fieldName = field;
                }

                string alias = tableAliasesByFieldPath[path];

                Select select = new Select()
                {
                    SelectOperand = (Base.Data.Operand.Field) $"{alias}.{fieldName}", Alias = $"{alias}_{fieldName}"
                };
                selectQuery.SelectList.Add(select);
            }

            selectQuery.WhereCondition = SearchCondition?.GetCondition(tableAliasesByFieldPath, upperFieldPath, queriesByFieldPath.Keys.Where(k => !string.IsNullOrEmpty(k)).ToArray());

            queriesByFieldPath[""] = new Tuple <ISelectQuery, Dictionary <string, string> >(selectQuery, tableAliasesByFieldPath);

            return(queriesByFieldPath);
        }