2010-05-12 4 views
4

Je crée une requête avec la bibliothèque dynamique LINQ, donc je ne connais pas le nombre de paramètres potentiels et j'obtiens une erreur lorsque j'essaie d'interroger les champs de type DATE:LINQ TO SQL, requête dynamique avec champs de type DATE

opérateur « > = » incompatible avec les types d'opérandes de la DateTime 'et « string »

Lorsque je fais un pas dans le débogueur dans les Dynamic.cs il montre que la valeur est de type chaîne et le champ est de type date donc le problème est évident mais je n'ai aucune idée de comment l'aborder.

Des idées?

BR

code:

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

Je pense que nous avons besoin de voir un peu de ce que votre code je s faire - Je ne pense pas que nous savons assez pour répondre sans beaucoup d'hypothèses et devine – Murph

Répondre

8

Vous devez utiliser une requête paramétrées, par exemple

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

Que faire si vous ne savez pas combien de paramètres potentiels y aura-t-il? – Acanthus

+1

Ensuite, vous construisez le tableau que vous allez. Ce n'est pas dur. –

8

J'étais dans le même bateau et j'étais capable de résoudre ceci en changeant une méthode dans la bibliothèque dynamique. C'est un hack, mais cela me permet d'utiliser des dates dans des expressions avec des opérateurs d'égalité (=,>, <, etc.).

Je poste le code ici au cas où quelqu'un s'en soucierait.
Le code que j'ajouté est dans le cas bloc autour de la ligne 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); 
    } 
} 

Le code vérifie essentiellement si vous essayez de comparer un champ de date (à gauche) avec une chaîne (à droite). Et puis il convertit l'expression droit à une date constante

est ici toute méthode 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

Great hack hack :) – kubal5003

+0

Vous avez raison à ce sujet. :) – boca

5

Parce que je devais faire une comparaison pour un DateTime? et j'ai fait cette modification.

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

Merci pour le tuyau!

+0

Mike avez-vous déjà fait une comparaison avec seulement la partie date de l'objet DateTime? Essayer de le faire pour le moment contre un Entity Framework Entity Object. J'ai essayé de modifier le code Dynamic Linq pour utiliser myProperty.Value.Date en utilisant la réflexion, mais pas de peur.Idéalement, je voudrais qu'il crée un lambda comme p => p.MyDateTimeProperty.Value.Date == "2012/08/01/plutôt que p => p.MyDateTimeProperty ==" 2012/08/01 ". celui-ci serait très apprécié – Cragly

8

J'ai eu le même problème, mais Boolean aussi bien, donc je généralise la solution

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

Les lignes dans la fonction principale deviennent alors ...

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

Seul inconvénient que je peux voir à cette approche est que si l'analyse échoue, nous allons lever et exception, mais étant donné que nous en jetons un de toute façon, je ne vois pas que cela importe trop

+1

où avez-vous mis ce code dans Dynamic.cs? – Staeff