public static Boolean EvaluateBoolean(TParams AParams, String AExpression, Boolean ADefault = false, SqlConnection AContextConnection = null)
        {
            if (String.IsNullOrEmpty(AExpression)) return ADefault;

              object LResult = InternalEvaluate(AParams, "SELECT Cast(1 AS Bit) WHERE (" + AExpression + ")", AContextConnection);
              if (LResult == null || LResult == DBNull.Value) return false;
              return (Boolean)LResult;
        }
        protected static String Format(String AFormat, TParams AParams)
        {
            const Char CParamChar  = ':';
              const Char CStickQuote = '|';
              const Char CEqualQuote = '=';

              if (String.IsNullOrEmpty(AFormat))
            return AFormat;

              int LStartIndex = 0;
              StringBuilder LResult = new StringBuilder(AFormat.Length);

              while (true)
              {
            if (LStartIndex >= AFormat.Length) break;
            int LIndex = AFormat.IndexOf(CParamChar, LStartIndex);                  // Находим ":" - начало переменной для замены

            Char LRightQuote;
            if ((LIndex < 0) || (LIndex == AFormat.Length - 1))                     // последний букавок в строке
            {
              LResult.Append(AFormat, LStartIndex, AFormat.Length - LStartIndex);   // не осталось переменных для автозамены выходим
              break;
            }
            if (LIndex > LStartIndex)
            {
              LResult.Append(AFormat, LStartIndex, LIndex - LStartIndex);           // не осталось переменных для автозамены выходим
              LStartIndex = LIndex;
            }

            LIndex++;  //Двигаемся на 1 элемент вперед
            int LRightQuoteIndex = -1;

            //Ожидаем квотик
            switch (AFormat[LIndex])
            {
              case '{':
            LRightQuote = '}';
            break;
              case '[':
            LRightQuote = ']';
            break;
              case CParamChar: //попалось еще ":" - превратим их 2х в 1
            LResult.Append(AFormat, LStartIndex, LIndex - LStartIndex);
            LStartIndex = LIndex + 1;
            continue;

              default: //Нету квотика значит это было ввообще не наше двоеточие
            char LChar = AFormat[LStartIndex];

            #region NotQoutedName
            LRightQuote = '0';
            LRightQuoteIndex = LIndex;
            while (LRightQuoteIndex < AFormat.Length)
            {
              LChar = AFormat[LRightQuoteIndex];
              if (
                      (LChar >= 'A') && (LChar <= 'Z')
                      ||
                      (LChar >= 'a') && (LChar <= 'z')
                      ||
                      (LChar >= '0') && (LChar <= '9')
                      ||
                      (LChar == '_') || (LChar == '#') || (LChar == '.') || (LChar == '{') || (LChar == '}')
                  )
                LRightQuoteIndex++;
              else
                break;

            }
            break;
            #endregion
            }

            //Нашли левый квотик ищем где же правый
            String LParamName     = null;
            String LDisplayType   = null;
            String LDisplayFormat = null;
            String LNullValue     = null;

            if (LRightQuoteIndex >= 0)
            {
              LParamName = AFormat.Substring(LIndex, LRightQuoteIndex - LIndex);
              LRightQuoteIndex--;
            }
            else
            {
              LRightQuoteIndex = AFormat.IndexOf(LRightQuote, LIndex + 1);

              if (LRightQuoteIndex < 0) //не нашли
              {
            LResult.Append(AFormat, LStartIndex, AFormat.Length - LStartIndex);
            break;
              }
              LResult.Append(AFormat, LStartIndex, LIndex - LStartIndex - 1);
              //Теперь у нас имя от LIndex до LRightQuoteIndex парсим его

              int EqualIndex = AFormat.IndexOf(CEqualQuote, LIndex, LRightQuoteIndex - LIndex); //находим знак равно

              int TypeIndex = AFormat.IndexOf(CStickQuote, LIndex, LRightQuoteIndex - LIndex); //находим палку
              int NullIndex = -1;

              if (EqualIndex > 0)
              {
            if (TypeIndex > EqualIndex)
            {
              NullIndex = TypeIndex;
              TypeIndex = -1;
            }
            else
            {
              NullIndex = AFormat.IndexOf(CStickQuote, EqualIndex, LRightQuoteIndex - EqualIndex);
            }
              }

              if ((TypeIndex > LIndex + 1) && (TypeIndex < LRightQuoteIndex))
              {
            LParamName = AFormat.Substring(LIndex + 1, TypeIndex - LIndex - 1);
            if (EqualIndex > 0)
              LDisplayType = AFormat.Substring(TypeIndex + 1, EqualIndex - TypeIndex - 1);
            else
              LDisplayType = AFormat.Substring(TypeIndex + 1, LRightQuoteIndex - TypeIndex - 1);
              }

              if (EqualIndex > 0)
              {
            if (LParamName == null)
              LParamName = AFormat.Substring(LIndex + 1, EqualIndex - LIndex - 1);

            if (NullIndex > 0)
            {
              LDisplayFormat = AFormat.Substring(EqualIndex + 1, NullIndex - EqualIndex - 1);
              LNullValue = AFormat.Substring(NullIndex + 1, LRightQuoteIndex - NullIndex - 1);
            }
            else
            {
              LDisplayFormat = AFormat.Substring(EqualIndex + 1, LRightQuoteIndex - EqualIndex - 1);
            }
              }
              if (LParamName == null)
              {
            LParamName = AFormat.Substring(LIndex + 1, LRightQuoteIndex - LIndex - 1);
              }
            }

            Object LValue;
            if (AParams == null || !AParams.FData.TryGetValue(LParamName, out LValue))
            {
              if (LNullValue == null)
            return null;
              else
            LResult.Append(LNullValue);
            }
            else
            {
              FormatTypes
            LFormat = (LDisplayType == null)
                      ?
                        FormatTypes.String
                        :
                        (FormatTypes)System.Enum.Parse(typeof(FormatTypes), LDisplayType, true);
              if (LValue == null)
              {
            if (LNullValue == null)
              return null;
            else
              LResult.Append(LNullValue);
              }
              else if (String.IsNullOrEmpty(LDisplayFormat))
            LResult.Append(LValue.ToString());
              else
              {
            switch (LFormat)
            {
              case FormatTypes.Bit:
              case FormatTypes.Boolean:
                try
                {
                  LResult.Append(Formats.FormatBoolean(LDisplayFormat, AsBit(LValue).IsTrue));
                }
                catch (Exception E)
                {
                  throw new Exception("Ошибка форматирования Boolean = " + LValue.ToString() + ": " + E.Message);
                }
                break;

              case FormatTypes.TinyInt:
              case FormatTypes.SmallInt:
              case FormatTypes.Int:
              case FormatTypes.BigInt:
              case FormatTypes.Hex:
                try
                {
                  LResult.Append(Formats.InternalFormatInteger(LDisplayFormat, AsBigInt(LValue).Value));
                }
                catch (Exception E)
                {
                  throw new Exception("Ошибка форматирования Int64 = " + LValue.ToString() + ": " + E.Message);
                }
                break;

              case FormatTypes.Date:
              case FormatTypes.Time:
              case FormatTypes.DateTime:
                try
                {
                  LResult.Append(Formats.FormatDateTime2(LDisplayFormat, AsDateTime2(LValue)));
                }
                catch (Exception E)
                {
                  throw new Exception("Ошибка форматирования DateTime = " + LValue.ToString() + ": " + E.Message);
                }
                break;

              case FormatTypes.DateTimeOffset:
                try
                {
                  LResult.Append(Formats.FormatDateTimeOffset(LDisplayFormat, AsDateTimeOffset(LValue)));
                }
                catch (Exception E)
                {
                  throw new Exception("Ошибка форматирования DateTimeOffset = " + LValue.ToString() + ": " + E.Message);
                }
                break;

              case FormatTypes.VarChar:
              case FormatTypes.NVarChar:
              case FormatTypes.String:
                LResult.Append(Formats.FormatString(Int16.Parse(LDisplayFormat), LValue.ToString()));
                break;

              case FormatTypes.Float:
              case FormatTypes.Decimal:
              case FormatTypes.Numeric:
                try
                {
                  LResult.Append(Formats.InternalFormatDecimal(LDisplayFormat, LValue.ToString(), "."));
                }
                catch (Exception E)
                {
                  throw new Exception("Ошибка форматирования Decimal = " + LValue.ToString() + ": " + E.Message);
                }
                break;
            }
              }
            }
            LStartIndex = LRightQuoteIndex + 1;
              }
              return LResult.ToString();
        }
        public static object Evaluate(TParams AParams, String AExpression, SqlConnection AContextConnection = null)
        {
            if (String.IsNullOrEmpty(AExpression)) return null;

              return InternalEvaluate(AParams, "SELECT (" + AExpression + ")", AContextConnection);
        }
        public void LoadFromString(
      String              AString,
      Char                ASeparator,
      TLoadValueCondition ALoadValueCondition = TLoadValueCondition.lvcAlways,
      Char                AParamPrefix        = '\0',
      TParams             AParams             = null
    )
        {
            if (String.IsNullOrEmpty(AString)) return;
              //TLoadValueCondition LLoadValueCondition = Pub.LoadValueConditionParser(ALoadValueCondition);

              Pub.NamedItemsParser Parser =
            new Pub.NamedItemsParser
            (
              AString,
              new Char[] { ASeparator, '\r', '\n' },
              true
             );

              while (Parser.MoveNext())
              {
            try
            {
              String LName  = Parser.Current.Name.Trim();
              String SValue = Parser.Current.Value;
              if(Parser.Current.Quote == '\0')
            SValue = SValue.Trim();

              Object LValue;
              if
              (
            AParamPrefix != '\0'
                && Parser.Current.Quote == '\0'
                //&& String.IsNullOrEmpty(Parser.Current.CastAs)
                && !String.IsNullOrEmpty(SValue)
                && SValue[0] == AParamPrefix
              )
              {
            if (AParams != null && AParams.FData.TryGetValue(SValue.Substring(1), out LValue))
            {
              if (ALoadValueCondition != TLoadValueCondition.lvcIfNotPresent || !FData.ContainsKey(LName))
                AddParam(LName, LValue);
            }
            else if (ALoadValueCondition == TLoadValueCondition.lvcAlways)
              AddParam(LName, DBNull.Value);
              }
              else if (ALoadValueCondition != TLoadValueCondition.lvcIfNotPresent || !FData.ContainsKey(LName))
              {
            // Парсим значение
            SqlDbType LSqlDbType = Sql.TypeFromString(Parser.Current.CastAs);

            if (LSqlDbType == SqlDbType.Udt)
              LValue = new SqlUdt(Parser.Current.CastAs, SValue);
            else
              LValue = Sql.ValueFromString(SValue, LSqlDbType, Sql.ValueDbStyle.SQL);
            AddParam(LName, LValue);
              }

            }
            catch (Exception E)
            {
              throw new Exception(String.Format("Неверно задано значение TParams '{0}': {1}", AString, E.Message));
            }
              }
        }
 public static SqlString AsSqlString(TParams AParams, String AName)
 {
     if(AParams == null) return SqlString.Null;
       return AParams.AsSqlString(AName);
 }
 /// <summary>
 /// Возвращает пересечение двух списков параметров
 /// </summary>
 /// <param name="value"></param>
 /// <returns></returns>
 //protected void CrossParams(TParams AParams)
 //{
 //  if (AParams == null)
 //  {
 //    Clear();
 //    return;
 //  };
 //  List<String> LKeys = new List<String>();
 //  foreach (KeyValuePair<String, Object> LDataPair in AParams.FData)
 //  {
 //    Object LValue;
 //    if (FData.TryGetValue(LDataPair.Key, out LValue))
 //      if(EqualValues(LValue, LDataPair.Value)) LKeys.Add(LDataPair.Key);
 //  }
 //  for (Int32 i = FData.Count - 1; i >= 0; i--)
 //  {
 //    if (LKeys.IndexOf(FData.Keys[i]) < 0) FData.RemoveAt(i);
 //  }
 //  return;
 //}
 /// <summary>
 /// Объединяет два списка параметров и возвращает результат
 /// </summary>
 protected void MergeParams(TParams ASource)
 {
     if (ASource == null) return;
       foreach (KeyValuePair<String, Object> LDataPair in ASource.FData)
     if (LDataPair.Key[0] != '=')
       AddParam(LDataPair.Key, LDataPair.Value);
 }
        /// <summary>
        /// Удаляет параметры из списка параметров
        /// </summary>
        /// <param name="name"></param>
        protected void Load(TParams ASource, String AAliases, TLoadValueCondition ALoadValueCondition = TLoadValueCondition.lvcAlways)
        {
            if (ASource == null) return;

              String LTarget, LSource;
              foreach (String LAlias in AAliases.Split(';'))
              {
            int LEqual = LAlias.IndexOf('=');
            if (LEqual == -1)
            {
              LTarget = LAlias;
              LSource = LAlias;
            }
            else
            {
              LTarget = LAlias.Substring(0, LEqual);
              LSource = LAlias.Substring(LEqual + 1);
            }

            Object LValue;
            if (ASource.FData.TryGetValue(LSource, out LValue))
            {
              if (ALoadValueCondition != TLoadValueCondition.lvcIfNotPresent || !FData.ContainsKey(LTarget))
            AddParam(LTarget, LValue);
            }
            else if (ALoadValueCondition == TLoadValueCondition.lvcAlways)
              AddParam(LTarget, DBNull.Value);
              }
        }
        /// <summary>
        /// Определяет, равны ли списки параметров
        /// </summary>
        /// <param name="arg"></param>
        /// <returns>Список параметров, который требуется сравнить с текущим</returns>
        protected bool Equals(TParams AParams)
        {
            if (AParams == null) return false;
              if (FData.Count != AParams.FData.Count) return false;

              foreach (KeyValuePair<String, Object> LDataPair in FData)
            if (LDataPair.Key[0] != '=')
            {
              Object LValue;
              if (!AParams.FData.TryGetValue(LDataPair.Key, out LValue)) return false;
              if (!EqualValues(LValue, LDataPair.Value)) return false;
            }
              return true;
        }
        //public void AddVarCharMax(String AName, SqlBytes AValue)
        //{
        //  if(AValue == null)
        //    DeleteParam(AName);
        //  else
        //    AddParam(AName, new Sql.SqlAnsiString(AValue.Value));
        //}
        /// <summary>
        /// Проверяет пересечение параметров, если общие параметры равны, то истина иначе ложь
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        protected Boolean Crossing(TParams AParams)
        {
            // -=MD=-: Я посчитал что правильно вернуть фальс
              // if (IsNull || value.IsNull) return false;

              if (AParams == null) return true;
              foreach (KeyValuePair<String, Object> LDataPair in AParams.FData)
            if (LDataPair.Key[0] != '=')
            {
              Object LValue;
              if (FData.TryGetValue(LDataPair.Key, out LValue))
            if (!EqualValues(LValue, LDataPair.Value))
              return false;
            }
              return true;
        }
        public static object InternalEvaluate(TParams AParams, String AExpression, SqlConnection AContextConnection = null)
        {
            if(AContextConnection == null)
            if(AParams == null)
            {
              AContextConnection = new SqlConnection(Const_ContextConnection);
              AContextConnection.Open();
            }
            else
            {
              AParams.InitContextConnection();
              AContextConnection = AParams.ContextConnection;
            }

              SqlCommand LSqlCommand = AContextConnection.CreateCommand();
              LSqlCommand.CommandText = AExpression; //"SELECT (" + AExpression + ")";
              LSqlCommand.CommandType = CommandType.Text;

              Sql.ParamsParser Parser =
            new Sql.ParamsParser
            (
              AExpression,
              '@',
              TCommentMethods.None,
              new char[0],
              new char[] {'\''}
             );

              while (Parser.MoveNext() && !String.IsNullOrEmpty(Parser.Current.Value))
            if (LSqlCommand.Parameters.IndexOf('@' + Parser.Current.Value) == -1)
            {
              Object LValue;
              if (AParams != null && AParams.FData.TryGetValue(Parser.Current.Value, out LValue))
            LSqlCommand.Parameters.AddWithValue('@' + Parser.Current.Value, LValue).Direction = ParameterDirection.Input;
              else
            LSqlCommand.Parameters.Add('@' + Parser.Current.Value, SqlDbType.VarChar, 1).Direction = ParameterDirection.Input;
            }

              return LSqlCommand.ExecuteScalar();
        }