2010-05-12 84 views
4

我正在用LINQ动态库构建查询,因此我不知道将有多少潜在参数,并且在尝试查询DATE类型字段时遇到错误:LINQ TO SQL,使用DATE类型字段进行动态查询

运算符“> =”与操作数类型的“日期时间”和“字符串”不相容

当我穿过的Dynamic.cs调试步骤它表明值是字符串类型和场是类型的日期,所以问题是显而易见的,但我不知道如何处理它。

任何想法?

BR

代码:

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

我认为我们需要看到你的代码一世这样做 - 我不认为我们知道足够的答案没有很多的假设和猜测 – Murph 2010-05-12 11:00:24

回答

8

你必须使用参数化查询,例如

using (MyEntities db = new MyEntities()) 
{ 
    String SQLparam = "CreateDate >= @1"; 
    List<UserList> UserList = db.UserList.Where(SQLparam, new [] { DateTime.Now }).ToList(); 
} 
+0

如果你不知道有多少潜在的参数会怎么样? – Acanthus 2010-05-12 15:28:50

+1

然后,您会随时建立阵列。这并不难。 – 2010-05-12 15:50:19

8

我在同一条船上,我可以通过更改动态库中的一种方法来解决此问题。这是一个黑客攻击,但它允许我在表达式中使用等号运算符的日期(=,>,<等)。

我在这里发布代码以防万一有人在意。
我添加的代码是在如果块周围线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; 
    } 
+0

非常丑陋的黑客:) – kubal5003 2011-11-07 16:14:29

+0

你说的对。 :) – boca 2011-11-09 20:24:48

5

因为我不得不做出一个日期时间的比较?我做了这个修改。

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); 
    } 
} 

感谢您的提示!

+0

迈克你有没有必要做一个比较日期时间对象的日期部分?试图在此时针对实体框架实体对象执行此操作。已尝试修改动态Linq代码使用myProperty.Value.Date使用反射,但不要害怕。理想情况下,我希望它创建一个lambda,如p => p.MyDateTimeProperty.Value.Date ==“2012/08/01 /而不是p => p.MyDateTimeProperty ==”2012/08/01“。这一个将不胜感激。 – Cragly 2012-08-28 20:04:33

8

我有同样的问题,但布尔一样,所以我广义的解决方案

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); 
} 

唯一的缺点我能看到这种方法是,如果解析失败,我们会提出和例外,但鉴于我们抛出一个无论如何,我不觉得它太重要

+1

你在Dynamic.cs中把这个代码放在哪里? – Staeff 2013-04-24 08:53:44