LINQ TO SQL, динамический запрос с полями типа DATE - PullRequest
5 голосов
/ 12 мая 2010

Я создаю запрос с помощью динамической библиотеки LINQ, поэтому я не знаю, сколько у меня будет потенциальных параметров, и я получаю сообщение об ошибке при попытке запросить поля типа DATE:

Оператор '> =' несовместим с типами операндов 'DateTime' и 'String'

Когда я прохожу отладчик в Dynamic.cs, он показывает, что значение имеет тип string, а поле - тип date, поэтому проблема очевидна, но я не знаю, как к ней подойти.

Есть идеи?

BR

Код:

using (MyEntities db = new MyEntities())
{
String SQLparam = "CreateDate >= \"" + DateTime.Now.ToShortDateString() + "\"";
List<UserList> UserList = db.UserList.Where(SQLparam).ToList();
}

Ответы [ 4 ]

9 голосов
/ 09 июня 2011

У меня была такая же проблема, но и с логическим значением, поэтому я обобщил решение

    Expression ConstantParser<T>(Expression left, Token op, Expression right, Func<string, T> parser)
    {
        if (right is ConstantExpression)
        {
            try
            {
                var value = ((ConstantExpression)right).Value.ToString();
                return Expression.Constant(parser(value));
            }
            catch (Exception)
            {
                throw IncompatibleOperandsError(op.text, left, right, op.pos);  
            }
        }

        throw IncompatibleOperandsError(op.text, left, right, op.pos);  
    }

Строки в основной функции становятся ...

else if (left.Type == typeof(DateTime) && right.Type == typeof(string))
{
    right = this.ConstantParser(left, op, right, DateTime.Parse);
}
else if (left.Type == typeof(DateTime?) && right.Type == typeof(string))
{
    right = this.ConstantParser(left, op, right, x => { DateTime? t = DateTime.Parse(x); return t; });
}
else if (left.Type == typeof(Boolean) && right.Type == typeof(string))
{
    right = this.ConstantParser(left, op, right, Boolean.Parse);
}

Единственный недостаток, который я вижу в этом подходе, заключается в том, что если анализ не удастся, мы будем повышать и делать исключение, но, учитывая, что мы все равно его выбрасываем, я не вижу, чтобы это имело слишком большое значение

9 голосов
/ 12 мая 2010

Вы должны использовать параметризованный запрос, например,

using (MyEntities db = new MyEntities())
{
    String SQLparam = "CreateDate >= @1";
    List<UserList> UserList = db.UserList.Where(SQLparam, new [] { DateTime.Now }).ToList();
}
8 голосов
/ 15 октября 2010

Я был в одной лодке, и мне удалось решить эту проблему, изменив один метод в динамической библиотеке. Это взлом, но он позволяет мне использовать даты в выражениях с операторами равенства (=,>, <и т. Д.). </p>

Я выкладываю код здесь на тот случай, если кому-то все равно.
Код, который я добавил, находится в блоке if в строке 53

else if (left.Type == typeof(DateTime) && right.Type == typeof(string))
{
    if (right is ConstantExpression)
    {
        DateTime datevalue;
        string value = ((ConstantExpression) right).Value.ToString();
        if (DateTime.TryParse(value, out datevalue))
        {
            right = Expression.Constant(datevalue);
        }
        else
        {
            throw IncompatibleOperandsError(op.text, left, right, op.pos);
        }
    }
    else
    {
        throw IncompatibleOperandsError(op.text, left, right, op.pos);
    }
}

Код в основном проверяет, пытаетесь ли вы сравнить поле даты (слева) со строкой (справа). И тогда он преобразует правильное выражение в константу даты

Вот весь метод ParseComparison:

        // =, ==, !=, <>, >, >=, <, <= operators
    Expression ParseComparison()
    {
        Expression left = ParseAdditive();
        while (token.id == TokenId.Equal || token.id == TokenId.DoubleEqual ||
            token.id == TokenId.ExclamationEqual || token.id == TokenId.LessGreater ||
            token.id == TokenId.GreaterThan || token.id == TokenId.GreaterThanEqual ||
            token.id == TokenId.LessThan || token.id == TokenId.LessThanEqual)
        {
            Token op = token;
            NextToken();
            Expression right = ParseAdditive();

            bool isEquality = op.id == TokenId.Equal || op.id == TokenId.DoubleEqual ||
                op.id == TokenId.ExclamationEqual || op.id == TokenId.LessGreater;
            if (isEquality && !left.Type.IsValueType && !right.Type.IsValueType)
            {
                if (left.Type != right.Type)
                {
                    if (left.Type.IsAssignableFrom(right.Type))
                    {
                        right = Expression.Convert(right, left.Type);
                    }
                    else if (right.Type.IsAssignableFrom(left.Type))
                    {
                        left = Expression.Convert(left, right.Type);
                    }
                    else
                    {
                        throw IncompatibleOperandsError(op.text, left, right, op.pos);
                    }
                }
            }
            else if (IsEnumType(left.Type) || IsEnumType(right.Type))
            {
                if (left.Type != right.Type)
                {
                    Expression e;
                    if ((e = PromoteExpression(right, left.Type, true)) != null)
                    {
                        right = e;
                    }
                    else if ((e = PromoteExpression(left, right.Type, true)) != null)
                    {
                        left = e;
                    }
                    else
                    {
                        throw IncompatibleOperandsError(op.text, left, right, op.pos);
                    }
                }
            }
            else if (left.Type == typeof(DateTime) && right.Type == typeof(string))
            {
                if (right is ConstantExpression)
                {
                    DateTime datevalue;
                    string value = ((ConstantExpression) right).Value.ToString();
                    if (DateTime.TryParse(value, out datevalue))
                    {
                        right = Expression.Constant(datevalue);
                    }
                    else
                    {
                        throw IncompatibleOperandsError(op.text, left, right, op.pos);
                    }
                }
                else
                {
                    throw IncompatibleOperandsError(op.text, left, right, op.pos);
                }
            }
            else
            {
                CheckAndPromoteOperands(isEquality ? typeof(IEqualitySignatures) : typeof(IRelationalSignatures),
                    op.text, ref left, ref right, op.pos);
            }
            switch (op.id)
            {
                case TokenId.Equal:
                case TokenId.DoubleEqual:
                    left = GenerateEqual(left, right);
                    break;
                case TokenId.ExclamationEqual:
                case TokenId.LessGreater:
                    left = GenerateNotEqual(left, right);
                    break;
                case TokenId.GreaterThan:
                    left = GenerateGreaterThan(left, right);
                    break;
                case TokenId.GreaterThanEqual:
                    left = GenerateGreaterThanEqual(left, right);
                    break;
                case TokenId.LessThan:
                    left = GenerateLessThan(left, right);
                    break;
                case TokenId.LessThanEqual:
                    left = GenerateLessThanEqual(left, right);
                    break;
            }
        }
        return left;
    }
5 голосов
/ 03 декабря 2010

Потому что я должен был сделать сравнение для DateTime? и я должен был сделать эту модификацию.

else if (left.Type == typeof(DateTime?) && right.Type == typeof(string))
{
  if (right is ConstantExpression)
  {
    DateTime datevalue;
    string value = ((ConstantExpression)right).Value.ToString();
    if (DateTime.TryParse(value, out datevalue))
    {
      DateTime? nullableDateValue = datevalue;
      right = Expression.Constant(nullableDateValue, typeof(DateTime?));
    }
    else
    {
      throw IncompatibleOperandsError(op.text, left, right, op.pos);
    }
  }
  else
  {
    throw IncompatibleOperandsError(op.text, left, right, op.pos);
  }
}

Спасибо за совет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...