public List<TemplateNodeUpdateJob> GetJobs(TemplateNodeInfo node)
		{
			long templateNodeId = node.TemplateNodeId.GetValueOrDefault();

			List<ScheduleSettingsRow> rows = this._currentStorage.ScheduleSettingsTable
				.GetAllRowsByTemplateNodeId(templateNodeId);

			List<TemplateNodeUpdateJob> jobs = new List<TemplateNodeUpdateJob>();

			foreach (ScheduleSettingsRow row in rows)
			{
				if (row != null)
				{
					TemplateNodeUpdateJob job = this.CreateJob(row, node);

					jobs.Add(job);
				}
				else
				{
					jobs.Add(TemplateNodeUpdateJob.Empty);
				}
			}

			return jobs;
		}
		public void SaveRequestedData(
			TemplateNodeInfo     templateNodeInfo,
			MultyQueryResultInfo results
		)
		{
			this._storageManager.SaveRequestedData(templateNodeInfo, results);
		}
        /// <summary>
        /// Get Id for data
        /// </summary>
        /// <param name="connectionGroup">Connection group</param>
        /// <param name="templateNode">Template node</param>
        /// <returns></returns>
        public Int64? GetId(ConnectionGroupInfo connectionGroup, TemplateNodeInfo templateNode)
        {
            Debug.Assert(!templateNode.IsInstance);

            Int64? parentId = null;

            if (templateNode.Parent != null)
            {
                parentId = this.GetId(connectionGroup, templateNode.Parent);
            }

            long?                 templateId = Storage.TemplateDirectory.GetId(connectionGroup);
            TemplateNodeQueryInfo pq         = templateNode.GetParentQuery();

            object parentQueryId = pq != null
                ? (object) Storage.TemplateNodeQueryGroupDirectory.GetId(connectionGroup, pq)
                : null;

            return this.GetRecordIdByFields(
                this.CreateField(TemplateIdFn,                 templateId),
                this.CreateField(ParentIdFn,                   parentId),
                this.CreateField(UserIdFieldName,              templateNode.Id),
                this.CreateField(NameFn,                       templateNode.Name),
                this.CreateField(IconFieldName,                templateNode.IconImageReferenceName),
                this.CreateField(ShowIfEmptyFieldName,         !templateNode.HideEmptyResultDatabases),
                this.CreateField(ShowNumberOfRecordsFieldName, templateNode.ShowNumberOfRecords),
                this.CreateField(ParentQueryGroupIdFn,         parentQueryId)
            );
        }
Example #4
0
        public TemplateNodeInfo CloneNotSavedTree(
            Dictionary <TemplateNodeInfo, TemplateNodeInfo> originalsAndClones,
            ConnectionData connectionData,
            TemplateNodeInfo parent = null
            )
        {
            TemplateNodeInfo clone = (TemplateNodeInfo)MemberwiseClone();

            clone._templateNodeId = null;
            clone.Parent          = parent;
            clone.Connection      = connectionData;
            clone.Childs          = new List <TemplateNodeInfo>(
                Childs.Select(
                    ch => ch.CloneNotSavedTree(
                        originalsAndClones,
                        connectionData,
                        clone
                        )
                    )
                );

            originalsAndClones.Add(this, clone);

            return(clone);
        }
        public abstract long? GetQueryId(
			TemplateNodeInfo      node,
			TemplateNodeQueryInfo templateNodeQuery,
			InstanceInfo          instance,
			DateTime              dateCreated,
			bool                  onlyFind
		);
Example #6
0
 /// <summary>
 ///     Constructor (without database).
 /// </summary>
 /// <param name="templateNode">Template node.</param>
 /// <param name="connection">Information group on connection.</param>
 public ConcreteTemplateNodeDefinition(TemplateNodeInfo templateNode, ConnectionGroupInfo connection)
 {
     this._templateNode = templateNode;
     this._group        = GroupDefinition.NullGroup;
     this.Connection    = connection;
     this.NodeActivated = true;
     this.NodeAvailable = true;
 }
Example #7
0
        /// <summary>
        ///     Constructor (with database).
        /// </summary>
        /// <param name="templateNode">Template node.</param>
        /// <param name="group">Database.</param>
        /// ///
        /// <param name="connection">Connection group information.</param>
        public ConcreteTemplateNodeDefinition(TemplateNodeInfo templateNode, GroupDefinition @group, ConnectionGroupInfo connection)
        {
            Debug.Assert(templateNode.IsInstance);

            this._templateNode = templateNode;
            this._group        = @group;
            this.Connection    = connection;
            this.NodeActivated = true;
            this.NodeAvailable = true;
        }
Example #8
0
        public TemplateNodeInfo GetRootPatent()
        {
            TemplateNodeInfo result = this;

            while (result.Parent != null)
            {
                result = result.Parent;
            }

            return(result);
        }
		public TemplateNodeQueryInfo()
		{
			this._queryFileName     = null;
			this._queryName         = null;
			this._resultHierarchy   = null;
			this._parameterValues   = null;
			this._id                = null;
			this._idsHierarchyCache = null;
			this.TemplateNode       = null;
			this._locales           = null;
		}
 public TemplateNodeQueryInfo()
 {
     this._queryFileName   = null;
     this._queryName       = null;
     this._resultHierarchy = null;
     this._parameterValues = null;
     this._id = null;
     this._idsHierarchyCache = null;
     this.TemplateNode       = null;
     this._locales           = null;
 }
Example #11
0
        private static IEnumerable <TemplateNodeInfo> InstantiateStaticNodes(
            IEnumerable <TemplateNodeInfo> templateNodes,
            ConnectionData connection,
            TemplateNodeInfo parent
            )
        {
            Debug.Assert(templateNodes.All(t => !t.IsInstance));
            Debug.Assert(parent.IsInstance);

            foreach (TemplateNodeInfo templateNode in templateNodes.Where(n => !n.NeedDataRowToBeInstantiated))
            {
                yield return(templateNode.Instantiate(connection, null, parent));
            }
        }
			public NodeAttirbutes(TemplateNodeInfo nodeInstance, DataRow dataRow = null) : this()
			{
				this._NodeInstance = nodeInstance;

				if (dataRow != null)
				{
					for (var i = 0; i < dataRow.Table.Columns.Count; i++)
					{
						var name = dataRow.Table.Columns[i].ColumnName;
						var value = dataRow[i].ToString();
						Values.Add(name, value);
					}

					this._Initialized = true;
				}
			}
Example #13
0
            public NodeAttirbutes(TemplateNodeInfo nodeInstance, DataRow dataRow = null) : this()
            {
                this._NodeInstance = nodeInstance;

                if (dataRow != null)
                {
                    for (var i = 0; i < dataRow.Table.Columns.Count; i++)
                    {
                        var name  = dataRow.Table.Columns[i].ColumnName;
                        var value = dataRow[i].ToString();
                        Values.Add(name, value);
                    }

                    this._Initialized = true;
                }
            }
		public List<TemplateNodeUpdateJob> LoadScheduleSettings(TemplateNodeInfo node, bool fromCache)
		{
			long                        templateNodeId = node.TemplateNodeId.GetValueOrDefault();
			List<TemplateNodeUpdateJob> result;

			if (fromCache)
			{
				result = Cache.GetOrAdd(
					GetCacheKey(templateNodeId),
					() => GetJobs(node)
				);
			}
			else
			{
				result = GetJobs(node);
			}

			return result;
		}
        /// <summary>
        /// Get ID for data
        /// </summary>
        /// <param name="connectionGroup">Connection group</param>
        /// <param name="templateNode">Template node</param>
        /// <param name="templateNodeQuery">Template node query</param>
        /// <returns></returns>
        public Int64? GetId(
			ConnectionGroupInfo   connectionGroup,
			TemplateNodeInfo      templateNode,
			TemplateNodeQueryInfo templateNodeQuery
		)
        {
            long? templateNodeId = Storage.TemplateNodeDirectory
                .GetId(connectionGroup, templateNode);

            string id        = templateNodeQuery.Id;
            string name      = templateNodeQuery.QueryName;
            string hierarchy = templateNodeQuery.ResultHierarchy;

            return this.GetRecordIdByFields(
                this.CreateField(TemplateNodeIdFieldName, templateNodeId),
                this.CreateField(UserIdFieldName,         id),
                this.CreateField(NameFieldName,           name),
                this.CreateField(HierarchyFieldName,      hierarchy)
            );
        }
        /// <summary>
        /// Reload template.
        /// </summary>
        public void ReloadTemplate()
        {
            if (ConnectionGroup == null)
            {
                throw new InvalidOperationException();
            }

            var           fileName                   = this._model.FilesProvider.GetTreeTemplateFileName(ConnectionGroup.TemplateFileName, ConnectionGroup.TemplateDir);
            string        startupTemplateId          = null;
            Stack<string> startupTemplateInfoIdStack = null;

            this.RootOfTemplate             = this._model.LoadTemplateNodes(fileName, ConnectionGroup.IsExternal, out startupTemplateId, out startupTemplateInfoIdStack);
            this.StartupTemplateId          = startupTemplateId;
            this.StartupTemplateInfoIdStack = startupTemplateInfoIdStack;

            if (RootOfTemplate.Childs.Count > 0)
            {
                ConnectionGroup.TemplateId = RootOfTemplate.Childs.First().TemplateId;
            }
        }
		public List<TemplateNodeUpdateJob> GetJobs(List<ScheduleSettingsRow> rows, TemplateNodeInfo node)
		{
			List<TemplateNodeUpdateJob> jobs = new List<TemplateNodeUpdateJob>();

			foreach (ScheduleSettingsRow row in rows)
			{
				if (row != null)
				{
					TemplateNodeUpdateJob job = this.CreateJob(row, node);

					jobs.Add(job);
				}
				else
				{
					jobs.Add(TemplateNodeUpdateJob.Empty);
				}
			}

			return jobs;
		}
Example #18
0
        public TemplateNodeInfo InstatiateStaticTree(ConnectionData connection, TemplateNodeInfo parent, Int64?id)
        {
            //Debug.Assert(parent == null || parent.IsInstance);
            //Debug.Assert(!this.IsInstance);

            var nodeInstance = this.IsInstance ? this : this.Instantiate(connection, null, parent);

            if (id != null)
            {
                nodeInstance.AssignTemplateId(id.Value);
            }

            nodeInstance.UpdateChildren(NodeUpdatingSource.LocallyOnly, null);

            foreach (var child in nodeInstance.Childs)
            {
                child.InstatiateStaticTree(connection, nodeInstance, null);
            }

            return(nodeInstance);
        }
Example #19
0
        public TemplateNodeInfo Instantiate(ConnectionData connection, string defaultDatabaseAttribute, TemplateNodeInfo parent)
        {
            Debug.Assert(!IsInstance);

            TemplateNodeInfo result = (TemplateNodeInfo)MemberwiseClone();

            result.Template                      = this;
            result.Attributes                    = new NodeAttirbutes(result);
            result.Childs                        = new List <TemplateNodeInfo>();
            result.Connection                    = connection;
            result.ReplicationSourceQuery        = null;
            result._defaultDatabaseAttributeName = defaultDatabaseAttribute;

            result.Queries           = Queries.Select(q => q.Clone()).ToList();
            result.ConnectionQueries = ConnectionQueries.Select(q => q.Clone()).ToList();
            result.GroupQueries      = GroupQueries.Select(q => q.Clone()).ToList();

            result.Parent = parent;

            return(result);
        }
        public void ReadTo(long nodeInstanceAttrId, TemplateNodeInfo.NodeAttirbutes attributes, SQLiteConnection cnn)
        {
            string sql = string.Format(
                "SELECT * FROM {0} WHERE {1} = {2}",
                TableName,
                NodeInstaceIdFn,
                nodeInstanceAttrId
            );

            using (SQLiteCommand cmd = new SQLiteCommand(sql, cnn))
            {
                using (SQLiteDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        attributes.Values[(string)reader[NameFn]] = (string)reader[ValueFn];
                        //attributes.Initialized = true;
                        //TODO KupVadim [20.12.2014 23:27]: This flag broken getter for UIid, NodeAttribute.GetUid()
                    }
                }
            }
        }
Example #21
0
        private TemplateNodeInfo Search(TemplateNodeInfo searchable)
        {
            if (this.TemplateNodeId == searchable.TemplateNodeId)
            {
                return(this);
            }

            foreach (var templateNodeInfo in this.Childs)
            {
                if (templateNodeInfo.TemplateNodeId == searchable.TemplateNodeId)
                {
                    return(templateNodeInfo);
                }

                var founded = templateNodeInfo.Search(searchable);

                if (founded != null)
                {
                    return(founded);
                }
            }

            return(null);
        }
		private Color GetColor(TemplateNodeInfo templateInfo)
		{
			return string.IsNullOrEmpty(templateInfo.FontColor)
				? Color.Black
				: Colors.FromString(templateInfo.FontColor);
		}
		public override long? GetQueryId(
			TemplateNodeInfo      node,
			TemplateNodeQueryInfo templateNodeQuery,
			InstanceInfo          instance,
			DateTime              dateCreated,
			bool                  onlyFind
		)
		{
			Int64? queryId = 0L;

			Debug.Assert(node.IsInstance);

			if (node.TemplateNodeId == null)
			{
				throw new InvalidOperationException();
			}

			Int64? templateNodeQueryId = Storage.TemplateNodeQueryDirectory
				.GetId(node.ConnectionGroup, node.Template, templateNodeQuery);

			Int64? serverId = Storage.ServerInstanceDirectory
				.GetId(node.ConnectionGroup, instance);

			if (onlyFind)
			{
				Tuple<long, long, long> key = new Tuple<Int64, Int64, Int64>(
					(long) node.TemplateNodeId.Value,
					(long) templateNodeQueryId,
					(long) serverId
				);

				return this.Cache.GetOrAdd(
					key, () =>
					{
						ITableRow row = this.NewRow();

						row.Values.Add(NodeInstanceIdFn,      node.TemplateNodeId.Value);
						row.Values.Add(TemplateNodeQueryIdFn, templateNodeQueryId);
						row.Values.Add(ServerInstanceIdFn,    serverId);

						queryId = this.GetRow(row);

						Log.InfoFormat("ServerId:'{0}';NodeInstanceId:'{1}';TemplateNodeQueryId:'{2}';PrimaryKey:'{3}'",
							serverId,
							node.TemplateNodeId.Value,
							templateNodeQueryId,
							queryId
						);

						return queryId;
					}
				);
			}

			List<Field> customFields = new List<Field>
			{
				this.CreateField(DefaultDatabaseNameFn,       node.GetDefaultDatabase()),
				this.CreateField(TableDefinition.DateCreated, dateCreated),
				this.CreateField(NodeInstanceIdFn,            node.TemplateNodeId.GetValueOrDefault()),
				this.CreateField(TemplateNodeQueryIdFn,       templateNodeQueryId),
				this.CreateField(ServerInstanceIdFn,          serverId)
			};

			queryId = this.GetRecordIdByFields(customFields.ToArray());

			Log.InfoFormat("ServerId:'{0}';NodeInstanceId:'{1}';TemplateNodeQueryId:'{2}';id:'{3}'",
				serverId,
				node.TemplateNodeId.GetValueOrDefault(),
				templateNodeQueryId,
				queryId
			);

			return queryId;
		}
		public void UpdateTreeNodeCounterValue(
			TemplateNodeInfo node,
			int?             counterValue
		)
		{
			int? currentValue = GetTreeNodeCounterValue(node);

			if (!Nullable.Equals(counterValue, currentValue))
			{
				NodeInstances.UpdateTreeNodeCounterValue(node, counterValue);
			}
		}
		public void UpdateTreeNodeTimings(
			TemplateNodeInfo     node,
			MultyQueryResultInfo results
		)
		{
			UpdateTreeNodeTimings(
				node,
				results.NodeLastUpdated,
				results.NodeLastUpdateDuration
			);
		}
		public ITableRow ReadLastMeta(
			TemplateNodeInfo      node,
			InstanceInfo          instance,
			TemplateNodeQueryInfo templateNodeQuery
		)
		{
			Int64? queryId = this.QueryDirectory.GetQueryId(
				node,
				templateNodeQuery,
				instance,
				new DateTime(),
				true
			);

			return queryId != null
				? this.ReadLastMeta(queryId.Value)
				: null;
		}
		private void FillTreeNodes(
			TemplateNodeInfo   parent,
			TreeNodeCollection treeNodes
		)
		{
			List<Tuple<TreeNode, ConcreteTemplateNodeDefinition>> pendingUpdateNodes =
				new List<Tuple<TreeNode, ConcreteTemplateNodeDefinition>>();

			Action action = () =>
			{
				treeNodes.Clear();

				treeNodes.AddRange(parent.Childs.Select(n =>
				{
					ConcreteTemplateNodeDefinition nodedef;
					TreeNode                       node = this._treeControl.CreateTreeViewNode(n, out nodedef);

					pendingUpdateNodes.Add(new Tuple<TreeNode, ConcreteTemplateNodeDefinition>(node, nodedef));

					return node;
				}).ToArray());

				if (parent.ChildrenAreLoadingNow)
				{
					treeNodes.Add(new TreeNode(this._treeControl._model.LocaleManager.GetLocalizedText(
						"common", "NodesQueryingTreeNodeText")
					)
					{
						ImageKey         = "NodesQuerying",
						SelectedImageKey = "NodesQuerying"
					});
				}
			};

			this._treeControl.SafeInvoke(action);

			foreach (Tuple<TreeNode, ConcreteTemplateNodeDefinition> pendingNode in pendingUpdateNodes)
			{
				TreeNode node                          = pendingNode.Item1;
				ConcreteTemplateNodeDefinition nodeDef = pendingNode.Item2;

				if (parent.IsDisabled)
				{
					nodeDef.TemplateNode.IsDisabled = true;
					nodeDef.NodeActivated           = false;
				}

				nodeDef.NodeAvailable = nodeDef.IsAvailableForDatabase(Program.Model) ?? true;

				if (!nodeDef.NodeAvailable)
				{
					this._treeControl.SetNotAvailableNode(node);
				}
				else
				{
					this._treeControl.SetNodeLoaded(node);

					List<TemplateNodeUpdateJob> refreshJobs = nodeDef.TemplateNode.GetRefreshJob(true);

					nodeDef.TemplateNode.HasActiveJobs = refreshJobs.Any(
						job =>
							job != null
							&& !job.IsEmpty()
							&& job.Enabled
					);

					UpdateTreeCounts(node, NodeUpdatingSource.LocallyOnly);
				}
			}
		}
Example #28
0
        public TemplateNodeInfo Instantiate(ConnectionData connection, DataRow row, TemplateNodeQueryInfo replicationSourceQuery, TemplateNodeInfo parent)
        {
            Debug.Assert(!IsInstance);
            Debug.Assert(NeedDataRowToBeInstantiated);

            var result = (TemplateNodeInfo)MemberwiseClone();

            result.Childs = new List <TemplateNodeInfo>();

            result.Template = this;

            result.Attributes = new NodeAttirbutes(result, row);
            result.Connection = connection;

            result.ReplicationSourceQuery = replicationSourceQuery;

            result.Queries           = Queries.Select(q => q.Clone()).ToList();
            result.ConnectionQueries = ConnectionQueries.Select(q => q.Clone()).ToList();
            result.GroupQueries      = GroupQueries.Select(q => q.Clone()).ToList();

            result.Parent = parent;
            result.Id     = null;
            result.Name   = Name + result.Id;

            result.OnAttributesChanged();

            return(result);
        }
Example #29
0
 public NodeAttirbutes()
 {
     this.Values        = new Dictionary <string, string>();
     this._NodeInstance = null;
     this._Initialized  = false;
 }
		private static IEnumerable<TemplateNodeInfo> ToPlainList(TemplateNodeInfo node)
		{
			var result = new List<TemplateNodeInfo> {node};

			foreach (var child in node.Childs)
			{
				result.AddRange(ToPlainList(child));
			}

			return result;
		}
        public void SaveTree(TemplateNodeInfo node)
        {
            this.Save(node);

            foreach (TemplateNodeInfo ch in node.Childs)
            {
                this.SaveTree(ch);
            }

            this.SetChildrenNotProcessedYet(node, false);
        }
		internal void ResetRowCountCache(TemplateNodeInfo node)
		{
			int oldValue = 0;

			if (node != null)
			{
				if (node.TemplateNodeId != null)
				{
					this._nodesRowCountCache.TryRemove(
						node.TemplateNodeId.Value,
						out oldValue
					);
				}
			}
		}
		internal void SaveMeta(
			TemplateNodeInfo     templateNodeInfo,
			MultyQueryResultInfo results,
			long                 requestId,
			DateTime             timestamp
		)
		{
			Debug.Assert(templateNodeInfo.IsInstance);

			Int64 sessionId          = 1L;
			List<ITableRow> metaRows = new List<ITableRow>();

			foreach (TemplateNodeResultItem tuple in results.List)
			{
				TemplateNodeQueryInfo templateNodeQuery = tuple.TemplateNodeQuery;
				QueryResultInfo       queryResult       = tuple.QueryResult;

				foreach (QueryInstanceResultInfo queryInstanceResult in queryResult.InstancesResult.Values)
				{
					InstanceInfo instance = queryInstanceResult.Instance;

					Int64? queryId = this.QueryDirectory.GetQueryId(
						templateNodeInfo,
						templateNodeQuery,
						instance,
						timestamp,
						false);

					Log.InfoFormat("Instance:'{0}';QueryId:'{1}'",
						instance,
						queryId
					);

					ITableRow row = this.MetaResultTable.GetMetaRow(
						requestId,
						sessionId,
						timestamp,
						queryInstanceResult,
						queryId,
						null
					);

					metaRows.Add(row);
				}
			}

			this.MetaResultTable.ReplaceRows(metaRows);

			this.ResetRowCountCache(templateNodeInfo);
		}
        public bool TryLoadChildren(TemplateNodeInfo node)
        {
            if (node.TemplateNodeId == null)
            {
                return false;
            }

            bool? notProcessedYet = this.GetChildrenNotYetProcessed(node.TemplateNodeId.Value);

            if (notProcessedYet ?? true)
            {
                return false;
            }

            String sql = string.Format(
                "SELECT I.{0}, I.*, PQ.{1}, T.{9} AS [TemplateUserId] " +
                "FROM {2} AS I " +
                "LEFT JOIN {3} AS T ON I.{7} = T.{13} " +
                "LEFT JOIN {4} AS PQ ON T.{8} = PQ.{14} " +
                "WHERE I.{5} = {6} AND I.{10} = {11} " +
                "ORDER BY I.{12}",
                IdentityField,
                TemplateNodeQueryGroupDirectory.DefaultDatabaseFieldFn,
                TableName,
                TemplateNodeDirectory.TableName,
                TemplateNodeQueryGroupDirectory.TableName,
                ParentIdFn,
                node.TemplateNodeId,
                TemplateNodeIdFn,
                TemplateNodeDirectory.ParentQueryGroupIdFn,
                TemplateNodeDirectory.UserIdFieldName,
                NodeEnabledFn,
                SqLiteBool.ToBit(true),
                NodeSequenceNumberFn,
                TemplateNodeDirectory.TableIdentityField,
                TemplateNodeQueryGroupDirectory.TableIdentityField
            );

            node.Childs.Clear();

            using (this.Connection.OpenWrapper())
            {
                new SqlSelectCommand(
                    this.Connection,
                    sql,
                    reader =>
                    {
                        string templateUserId = reader["TemplateUserId"].ToString();

                        TemplateNodeInfo template = node.Template.Childs.FirstOrDefault(
                            n => n.Id == templateUserId.ToString()
                        );

                        if (template == null)
                        {
                            this.DisableNode((Int64)reader[IdentityField]);
                            return;
                        }

                        string defaultDbFieldnName =
                            reader[TemplateNodeQueryGroupDirectory.DefaultDatabaseFieldFn].ToString();

                        TemplateNodeInfo newNode = template.Instantiate(node.Connection, defaultDbFieldnName, node);

                        long newNodeId = (Int64)reader[IdentityField];

                        newNode.AssignTemplateId(newNodeId);

                        List<TemplateNodeUpdateJob> refreshJobs = newNode.GetRefreshJob(true);

                        foreach (TemplateNodeUpdateJob refreshJob in refreshJobs)
                        {
                            if (refreshJob != null && !refreshJob.IsEmpty())
                            {
                                if (!(reader[NodeScheduledUpdateFn] is DBNull))
                                {
                                    refreshJob.LastRan = (DateTime)reader[NodeScheduledUpdateFn];
                                }
                            }
                        }

                        this._storage.NodeInstanceAttributes.ReadTo(
                            newNodeId,
                            newNode.Attributes,
                            this.Connection
                        );

                        newNode.OnAttributesChanged();

                        node.Childs.Add(newNode);
                    })
                .Execute(100);
            }

            Dictionary<string, TemplateNodeInfo> absent = new Dictionary<string, TemplateNodeInfo>();

            foreach (TemplateNodeInfo nodeTemplate in node.Template.Childs.Where(n => !n.NeedDataRowToBeInstantiated))
            {
                absent[nodeTemplate.Id] = nodeTemplate;
            }

            foreach (TemplateNodeInfo loaded in node.Childs)
            {
                absent.Remove(loaded.Template.Id);
            }

            if (absent.Any())
            {
                Dictionary<TemplateNodeInfo, int> templateIndexes = new Dictionary<TemplateNodeInfo, int>();

                for (int i = 0; i < node.Template.Childs.Count; i++)
                {
                    templateIndexes[node.Template.Childs[i]] = i;
                }

                List<TemplateNodeInfo> newStatics = absent.Values.Select(t => t.Instantiate(node.Connection, null, node)).ToList();

                IOrderedEnumerable<TemplateNodeInfo> newList =
                    new List<TemplateNodeInfo>(node.Childs).Union(newStatics).OrderBy(n => templateIndexes[n.Template]);

                node.Childs.Clear();

                node.Childs.AddRange(newList);

                this.SaveChildren(node);
            }

            return true;
        }
		internal int? GetRowCount(TemplateNodeInfo node)
		{
			Debug.Assert(node.IsInstance);

			int  cachedValue = 0;
			int? rowsTotal   = null;

			if (node.TemplateNodeId == null)
			{
				return null;
			}

			if (this._nodesRowCountCache.TryGetValue(node.TemplateNodeId.Value, out cachedValue))
			{
				return cachedValue;
			}

			foreach (InstanceInfo serverInstance in node.ConnectionGroup.Connections)
			{
				foreach (TemplateNodeQueryInfo tqi in node.Queries)
				{
					Int64? queryId = this.QueryDirectory.GetQueryId(
						node,
						tqi,
						serverInstance,
						new DateTime(),
						true
					);

					if (queryId == null)
					{
						continue;
					}

					if (rowsTotal == null)
					{
						rowsTotal = 0;
					}

					ITableRow lastMetaRow = this.ReadLastMeta(queryId.Value);

					rowsTotal += lastMetaRow != null
						? (int)(Int64)lastMetaRow.Values[MetaResultTable.RowCountFieldName]
						: 0;
				}
			}

			if (rowsTotal == null)
			{
				return null;
			}

			this._nodesRowCountCache.AddOrUpdate(node.TemplateNodeId.Value, id => rowsTotal.Value, (id, old) => rowsTotal.Value);

			//NodeInstances.SetReportsRowCountTotal(node.PrimaryKey.Value, rowsTotal.Value);

			return rowsTotal.Value;
		}
        public bool TryLoadRoodId(TemplateNodeInfo node, Int64? connectionGroupId, Int64? templatedId)
        {
            String sql = string.Format(
                "SELECT ni.[{8}] FROM [{0}] ni " +
                "JOIN [{4}] tn ON ni.[{5}] = tn.[{8}] " +
                "WHERE ni.[{1}] IS NULL AND ni.[{2}] = {3} " +
                "AND tn.[{6}] = {7}",
                TableName,
                ParentIdFn,
                ConnectionIdFn,
                connectionGroupId,
                TemplateNodeDirectory.TableName,
                TemplateNodeIdFn,
                TemplateNodeDirectory.TemplateIdFn,
                templatedId,
                TemplateNodeDirectory.TableIdentityField
            );

            using (this.Connection.OpenWrapper())
            {
                bool result = false;

                new SqlSelectCommand(
                    this.Connection,
                    sql,
                    reader =>
                    {
                        node.AssignTemplateId((Int64)reader[IdentityField]);
                        result = true;
                    })
                    .Execute(100);

                if (result)
                {
                    return true;
                }
            }

            return false;
        }
		public void Save(TemplateNodeInfo templateNodeInfo)
		{
			NodeInstances.Save(templateNodeInfo);

			templateNodeInfo.SaveUserParameters(this);
		}
        public void UpdateTreeNodeCounterValue(TemplateNodeInfo node, int? counterValue)
        {
            Debug.Assert(node.IsInstance);

            if (node.TemplateNodeId == null)
            {
                this.Save(node);
            }

            if (node.TemplateNodeId == null)
            {
                return;
            }

            using (this.Connection.OpenWrapper())
            {
                const string paramName = "@intCounterValue";

                string update = string.Format("UPDATE [{0}] SET [{1}] = {2}", TableName, NodeCounterValue, paramName);
                string whereClause = string.Format("[{0}] = {1}", IdentityField, node.TemplateNodeId.Value);

                SQLiteParameter parameter;

                if (counterValue != null)
                {
                    whereClause += string.Format(" AND ([{0}] IS NULL OR [{0}] != {1})", NodeCounterValue, paramName);
                    parameter = new SQLiteParameter(paramName, counterValue.Value);
                }
                else
                {
                    whereClause += string.Format(" AND [{0}] IS NOT NULL", NodeCounterValue);
                    parameter = new SQLiteParameter(paramName, DBNull.Value);
                }

                string query = string.Format(
                    "{0} WHERE {1};",
                    update,
                    whereClause
                );

                new SqlCustomCommand(this.Connection, query, parameter)
                    .Execute(100);
            }
        }
		public void UpdateTreeNodeTimings(
			TemplateNodeInfo node,
			DateTime?        lastUpdateDateTime,
			DateTime?        lastUpdateDuration
		)
		{
			NodeInstances.UpdateTreeNodeLastUpdateAndDuration(
				node,
				lastUpdateDateTime,
				lastUpdateDuration
			);
		}
        public void UpdateTreeNodeLastUpdateAndDuration(
			TemplateNodeInfo node,
			DateTime?        lastUpdateDateTime,
			DateTime?        lastUpdateDuration
		)
        {
            Debug.Assert(node.IsInstance);

            if (node.TemplateNodeId != null)
            {
                using (this.Connection.OpenWrapper())
                {
                    String query = string.Format(
                          "UPDATE [{0}] SET"
                        + "     [{1}] = @NodeLastUpdated"
                        + "    ,[{2}] = @NodeLastUpdateDuration"
                        + " WHERE"
                        + "    [{3}] = @{3}"
                        + "    AND ("
                        + "       ([{1}] IS NULL OR [{1}] != @NodeLastUpdated)"
                        + "       OR"
                        + "       ([{2}] IS NULL OR [{2}] != @NodeLastUpdateDuration)"
                        + "    );",
                        TableName,
                        NodeLastUpdated,
                        NodeLastUpdateDuration,
                        IdentityField
                    );

                    SQLiteParameter[] sqliteParameters = {
                        new SQLiteParameter("@NodeLastUpdated",        lastUpdateDateTime),
                        new SQLiteParameter("@NodeLastUpdateDuration", lastUpdateDuration),
                        new SQLiteParameter("@" + IdentityField,       node.TemplateNodeId.Value)
                    };

                    new SqlCustomCommand(this.Connection, query, sqliteParameters)
                        .Execute(0);
                }
            }
        }
		public int? GetTreeNodeCounterValue(TemplateNodeInfo node)
		{
			return NodeInstances.GetTreeNodeCounterValue(node);
		}
        private void SetChildrenNotProcessedYet(TemplateNodeInfo node, bool value)
        {
            Debug.Assert(node.IsInstance);
            Debug.Assert(node.TemplateNodeId != null);

            if (node.TemplateNodeId == null)
            {
                this.Save(node);
            }

            if (node.TemplateNodeId == null)
            {
                throw new InvalidOperationException(node + " is not saved (has no PrimaryKey)");
            }

            using (this.Connection.OpenWrapper())
            {
                String query = string.Format(
                    "UPDATE [{0}] SET [{1}] = {2} WHERE [{3}] = {4} AND ([{1}] IS NULL OR [{1}] != {2});",
                    TableName,
                    ChildrenNotYetProcessedFn,
                    SqLiteBool.ToBit(value),
                    IdentityField,
                    node.TemplateNodeId.Value
                );

                new SqlCustomCommand(this.Connection, query).Execute(1);
            }
        }