示例#1
0
        /// <summary>
        /// Called from Load after loading the top table to load all other tables.
        /// The base implementation is careful to only load a table once regardless of the number of detail levels and the number of parent/grandparent
        /// rows. For example for a persiston whose table structure is (Sale, LineItem, LineItemNote), then there will only be one select statement
        /// issued for LineItemNote, using an IN clause for the primary keys of LineItem (which were already loaded).
        /// (The call syntax would be complex to invoke this for the top table so this is called only once for the children of the top
        /// table.)
        /// </summary>
        /// <param name="parentRows">parent Row objects indexed by primary key value</param>
        protected async Task LoadChildTablesRecursive(Dictionary <object, Row> parentRows, IDbConnection db, DataDictionary dbdef, TableDef parentdef)
        {
            if (!parentRows.Any())
            {
                return;
            }
            if (parentdef.Children == null)
            {
                return;
            }

            //get parent keys in the form "1,2,3..."
            string parentKeyListFormatted = SqlSelectBuilder.FormatInClauseList(parentRows.Keys);

            foreach (var childTabledef in parentdef.Children)
            {
                //get rows - where clause is "parentkey in (...)"
                var whereClause = new SqlSelectBuilder.Where();
                whereClause.AddWhere($"{childTabledef.ParentKeyColumnName} in({parentKeyListFormatted})");
                var loadResult = await LoadTable(db, dbdef, childTabledef, whereClause, childTabledef.DefaulSortColName, 0, 0);

                var rowdict = loadResult.RowsByParentKey;

                //deal out the rows into the parent objects' Lists of this type
                var listField = parentdef.RowType.GetField(childTabledef.Name);
                foreach (object parentKey in rowdict.Keys)
                {
                    var rowsForParent = rowdict[parentKey];
                    var parentRow     = parentRows[parentKey];
                    var list          = Utils.CreateOrGetFieldValue <IList>(parentRow, listField);
                    foreach (var row in rowsForParent)
                    {
                        list.Add(row);
                    }
                }

                //recur
                var rowsByPK = RestructureByPrimaryKey(childTabledef, rowdict);
                await LoadChildTablesRecursive(rowsByPK, db, dbdef, childTabledef);
            }
        }
示例#2
0
        /// <summary>
        /// Load rows given by where clause for a table and return them as dictionary indexed by the parent key value.
        /// If there is no parent key for the table, then the dictionary will have one entry with key="".
        /// The returned list members are objects of the type indicated by tabledef.
        /// The implementation loads one additional row to determine whether the load was complete, if pageSize is nonzero.
        /// </summary>
        /// <param name="pageSize">if zero, does not do paging</param>
        /// <param name="whereClause">can be null</param>
        protected virtual Task <SingleLoadResult> LoadTable(IDbConnection db, DataDictionary dbdef, TableDef tabledef, SqlSelectBuilder.Where whereClause,
                                                            string sortColName, int pageSize, int pageNo)
        {
            var    colInfos          = BuildColumnsToLoadList(dbdef, tabledef);
            string parentKeyColName  = tabledef.ParentKeyColumnName;
            int    parentKeyColIndex = -1;
            var    columnNames       = colInfos.Select(c => c.SqlExpression).ToList();

            if (parentKeyColName != null)
            {
                parentKeyColIndex = columnNames.Count;
                columnNames.Add(parentKeyColName);
            }
            int customColIndex = -1;

            if (tabledef.HasCustomColumns)
            {
                customColIndex = columnNames.Count;
                columnNames.Add(CUSTOMCOLNAME);
            }
            var sql = new SqlSelectBuilder(SqlFlavor, tabledef.SqlTableName, sortColName, columnNames)
            {
                PageSize = pageSize,
                PageNo   = pageNo
            };

            if (whereClause != null)
            {
                sql.WhereClause = whereClause;
            }
            var  rowsByParentKey = new Dictionary <object, List <Row> >();
            bool isComplete      = true;

            using (var cmd = db.CreateCommand())
            {
                cmd.CommandText = CustomizeSqlStatement(sql.ToString());
                if (whereClause != null)
                {
                    whereClause.ExportParameters(cmd);
                }
                using (var reader = cmd.ExecuteReader())
                {
                    int rowsLoaded = 0;
                    while (reader.Read())
                    {
                        //if this is the throw-away row that was one more than the page size, then note as incomplete but don't look at it
                        if (++rowsLoaded > pageSize && pageSize > 0)
                        {
                            isComplete = false;
                            break;
                        }

                        //read parent key value
                        object pk = "";
                        if (parentKeyColIndex >= 0)
                        {
                            pk = reader.GetValue(parentKeyColIndex);
                        }

                        //read remaining values
                        var row = Utils.Construct(tabledef.RowType) as Row;
                        SetRowFromReader(colInfos, reader, row);

                        //read custom values
                        if (tabledef.HasCustomColumns)
                        {
                            string json = (string)Utils.ChangeType(reader.GetValue(customColIndex), typeof(string));
                            if (!string.IsNullOrEmpty(json))
                            {
                                SetRowFromCustomValues(json, tabledef, row);
                            }
                        }

                        //store in return dict
                        if (!rowsByParentKey.ContainsKey(pk))
                        {
                            rowsByParentKey[pk] = new List <Row>();
                        }
                        rowsByParentKey[pk].Add(row);
                    }
                }
            }
            var ret = new SingleLoadResult
            {
                RowsByParentKey = rowsByParentKey,
                IsComplete      = isComplete
            };

            return(Task.FromResult(ret));
        }