private static int UpdateAll(IConnectionProvider conn, IEntity rootEntity, DbRelation recursiveRelation, UpdateList setExpressions, int beginAtLevel, int endAtLevel)
        {
            // Stop condition: rowsAffected == 0
            int totalRowsAffected = 0;
            bool isLocalConn = !conn.IsOpen;
            try
            {
                if (isLocalConn)
                    conn.BeginTransaction();

                // We need to perform COUNT at least once to determine whether rowsAffacted returned by UPDATE can be trusted.
                RowsAffectedCredibility trustRowsAffected = RowsAffectedCredibility.NotDetermined;
                bool reachedEndLevel = false;
                int level = beginAtLevel;
                do
                {
                    // Dependening on DBMS configuration, update statements may automatically return the number of rows affected.
                    int rowsAffectedReturnedByEngine = UpdateAtLevel(conn, rootEntity, recursiveRelation, setExpressions, level);

                    // We need to perform manual counting for as long as rows affected cannot be trusted.
                    int? manualNodeCount = CountNodesAtLevelIfRowsAffectedCannotBeTrusted(conn, rootEntity, trustRowsAffected, recursiveRelation, level);                    
                    
                    // Evaluation which determines whether rows affected may be trusted takes place only once, ie. if not yet determined.
                    bool evaluateRowsAffectedCredibility = (trustRowsAffected == RowsAffectedCredibility.NotDetermined) && (manualNodeCount.HasValue);
                    if (evaluateRowsAffectedCredibility)
                    {
                        bool engineCountMatchesManualCount = (rowsAffectedReturnedByEngine == manualNodeCount.Value);
                        trustRowsAffected = (engineCountMatchesManualCount) ? RowsAffectedCredibility.Trusted : RowsAffectedCredibility.Untrusted;
                    }

                    // Manual node count is null if we have determined that rows affected value returned by engine is credible.
                    int rowsUpdatedInCurrentLevel = manualNodeCount ?? rowsAffectedReturnedByEngine;
                    totalRowsAffected += rowsUpdatedInCurrentLevel;
                    
                    // Inspect stop condition before level variable is increased.
                    reachedEndLevel = IsEndLevelReached(endAtLevel, level, rowsUpdatedInCurrentLevel);

                    // Next level.
                    level++;
                } while (!reachedEndLevel);

                if (isLocalConn)
                    conn.CommitTransaction();
            }
            finally
            {
                if (isLocalConn)
                    conn.CloseConnection();
            }

            return totalRowsAffected;
        }
        private static int UpdateWithLeafFilter(IConnectionProvider conn, IEntity rootEntity, DbRelation recursiveRelation, UpdateList setExpressions, SearchCondition leafFilter, int beginAtLevel, int endAtLevel)
        {
            // Stop condition: final level reached (tree depth is measured).
            // It's possible that at some intermediate levels no records satisfy the specified criteria.
            // Nevertheless, the algorithm must proceed to the next level where it might find matching records.
            // This behavior simulates the behavior of recursive CTEs.
            int totalRowsAffected = 0;
            bool isLocalConn = !conn.IsOpen;
            try
            {
                if (isLocalConn)
                    conn.BeginTransaction();

                endAtLevel = GetEndLevel(conn, rootEntity, recursiveRelation, endAtLevel);
                bool reachedEndLevel = false;
                int level = beginAtLevel;
                do
                {
                    UpdateStatement updateAtLevel = CreateUpdateLevelStatement(rootEntity, recursiveRelation, setExpressions, leafFilter, level);
                    totalRowsAffected += updateAtLevel.Execute(conn);

                    reachedEndLevel = (level >= endAtLevel);
                    level++;
                } while (!reachedEndLevel);

                if (isLocalConn)
                    conn.CommitTransaction();
            }
            finally
            {
                if (isLocalConn)
                    conn.CloseConnection();
            }

            return totalRowsAffected;
        }