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);
            }
        }
        public void DisableNode(Int64 nodeId)
        {
            using (this.Connection.OpenWrapper())
            {
                String query = string.Format(
                    "UPDATE [{0}] SET [{1}] = {2} WHERE [{3}] = {4} AND ([{1}] IS NULL OR [{1}] != {2});",
                    TableName,
                    NodeEnabledFn,
                    SqLiteBool.ToBit(false),
                    IdentityField,
                    nodeId
                    );

                new SqlCustomCommand(this.Connection, query)
                .Execute(100);
            }
        }
        public void DisableChildren(TemplateNodeInfo node)
        {
            Debug.Assert(node.IsInstance);

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

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

                new SqlCustomCommand(this.Connection, query)
                .Execute(100);
            }
        }
        public void Update(
            ConnectionGroupInfo connectionGroup,
            Int64 queryId,
            TemplateNodeQueryInfo query,
            List <ParameterValue> newValues
            )
        {
            Dictionary <long, ITableRow> existingRows = new Dictionary <Int64, ITableRow>();

            foreach (ITableRow row in this.GetRows(QueryIdFn + " = " + queryId))
            {
                existingRows[(Int64)row.Values[ParameterIdFn]] = row;
            }

            foreach (var value in newValues)
            {
                Int64?parameterId = GetParameterId(connectionGroup, query, value.Name);

                if (parameterId != null)
                {
                    existingRows.Remove((Int64)parameterId);
                }

                if (!this.ReadOnly)
                {
                    List <Field> fields = new List <Field> {
                        this.CreateField(ValueFn, value.UserValue),
                        this.CreateField(IsEnabledFn, true),
                        this.CreateField(QueryIdFn, queryId),
                        this.CreateField(ParameterIdFn, parameterId)
                    };

                    ITableRow row = this.NewRow();

                    foreach (Field field in fields)
                    {
                        if (field != null)
                        {
                            row.Values.Add(field.Item1, field.Item2);
                        }
                    }

                    this.InsertOrUpdateRow(row, this.BeforeRowUpdate, this.BeforeRowAdd);
                }
            }

            foreach (KeyValuePair <long, ITableRow> absent in existingRows)
            {
                string sqlQuery = string.Format(
                    "UPDATE {0} SET {1} = {2} WHERE [{4}] = {3} AND {1} != {2};",
                    GetTableName(),
                    IsEnabledFn,
                    SqLiteBool.ToBit(false),
                    absent.Key,
                    IdentityField
                    );

                new SqlCustomCommand(this.Connection, sqlQuery)
                .Execute(100);
            }
        }
        public static TableDefinition CreateTableDefinition()
        {
            TableDefinition nodeInstanceTableDefinition = TableDefinitionFactory.CreateWithAutoincrementKey(TableName, TableIdentityField)
                                                          .AddBigIntField(ConnectionIdFn, true, false)
                                                          .AddBigIntField(TemplateNodeIdFn, true, false)
                                                          .AddBigIntField(ParentIdFn, true, false)
                                                          .AddNVarCharField(NodeUIdFn, true, false)
                                                          .AddNVarCharField(NodeUNameFn, false, false)
                                                          .AddNVarCharField(NodeUIconFn, false, false)
                                                          .AddBitField(NodeEnabledFn, false, false, SqLiteBool.ToBit(true))
                                                          .AddNVarCharField(NodeFontColorFn, false, false)
                                                          .AddNVarCharField(NodeFontStyleFn, false, false)
                                                          .AddBigIntField(NodeSequenceNumberFn, true, false)
                                                          .AddBitField(ChildrenNotYetProcessedFn, false, false, SqLiteBool.ToBit(true))
                                                          .AddDateTimeField(NodeScheduledUpdateFn, false, false)
                                                          .AddIntField(NodeCounterValue, false, false)
                                                          .AddDateTimeField(NodeLastUpdated, false, false)
                                                          .AddDateTimeField(NodeLastUpdateDuration, false, false)
                                                          .AddDateCreateField()
                                                          .AddDateUpdatedField(TableIdentityField);

            nodeInstanceTableDefinition.Indexes.Add(
                new IndexDefinition(
                    nodeInstanceTableDefinition,
                    "Parent_idx",
                    false,
                    ParentIdFn
                    )
                );

            return(nodeInstanceTableDefinition);
        }
        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);
        }