代码之家  ›  专栏  ›  技术社区  ›  Muflix

LINQ2SQL表达式-转换日期时转换失败

  •  0
  • Muflix  · 技术社区  · 7 年前

    var searchDate = DateTime.ParseExact("17.12.2018", "dd.MM.yyyy", 
                                          CultureInfo.InvariantCulture, 
                                          DateTimeStyles.None);
    
    result = result.Where(DatePredicate("LaunchWeekStartDate", searchDate, 3));
    

    我把这个表达式叫做

    public static Expression<Func<General, bool>> DatePredicate(string columnName, 
                                                                DateTime 
                                                                searchValue, 
                                                                int? operatorId)
    {
      var type = typeof(General);
      var x = Expression.Parameter(type, "x");
      var member = Expression.Property(x, columnName);
      Expression expression;
    
      var constant = Expression.Constant(searchValue, typeof(DateTime));
    
      // Greater Than >
      if (operatorId == 2)
      {
        expression = Expression.GreaterThan(member, constant); // THIS THROW ERROR
        return Expression.Lambda<Func<General, bool>>(expression, x);
      }
    
      // Less Than <
      else if (operatorId == 4)
      {
        expression = Expression.LessThan(member, constant); // THIS THROW ERROR
        return Expression.Lambda<Func<General, bool>>(expression, x);
      }
    
      // Equal
      var column = type.GetProperties().FirstOrDefault(p => p.Name == columnName);
    
      expression = column == null
                 ? expression = Expression.Constant(true) // THIS WORKS
                 : expression = Expression.Equal(member, constant); // THIS THROW ERROR
    
      return Expression.Lambda<Func<General, bool>>(expression, x);
    }
    

    我得到的错误是

    System.Data.SqlClient.SqlException(0x80131904):从字符串转换日期和/或时间时转换失败。

    这很有效

    var searchDate = DateTime.ParseExact("17.12.2018", "dd.MM.yyyy", 
                                         CultureInfo.InvariantCulture, 
                                         DateTimeStyles.None);
    result = result.Where(x => x.LaunchWeekStartDate == searchDate);
    

    LaunchWeekStartDate的数据库列和类属性的类型为DateTime。

    public class General
        {
            [Key]
            public Int64 RowNumber {get; set;}
        // ...
            public DateTime LaunchWeekStartDate { get; set; }
        }
    

    请你解释一下这里的问题是什么?

    而不是 Express.Equal Express.Call 具有 CompareTo

    var member = Expression.Property(x, columnName);
    MethodInfo method = typeof(DateTime).GetMethod("CompareTo", new[] { typeof(DateTime) });
    constant = Expression.Constant(searchValue, typeof(DateTime));
    var call = Expression.Call(member, method, constant);
    return Expression.Lambda<Func<General, bool>>(call, x);
    

    System.ArgumentException:类型为“System.Int32”的表达式不能用于返回类型“System.Boolean”

    1 回复  |  直到 7 年前
        1
  •  2
  •   Wizzyno    5 年前

    在这篇帖子上查看我的答案 here

    解决方案是如何使EntityFramework生成带有参数的SqlCommand,以便数据类型映射可以将CLR DateTime转换为SQL Server等效项。

        2
  •  0
  •   Muflix    7 年前

    这很有效,我是从这个9年的博客上抄来的 https://www.tabsoverspaces.com/231060-comparing-date-only-in-ef

    expression = Expression.And(
                    Expression.Equal(
                        Expression.MakeMemberAccess(member, typeof(DateTime).GetMember("Day").Single()),
                        Expression.Constant(searchValue.Day)
                        ),
                    Expression.And(
                        Expression.Equal(
                            Expression.MakeMemberAccess(member, typeof(DateTime).GetMember("Month").Single()),
                            Expression.Constant(searchValue.Month)
                            ),
                        Expression.Equal(
                            Expression.MakeMemberAccess(member, typeof(DateTime).GetMember("Year").Single()),
                            Expression.Constant(searchValue.Year)
                            )
                        )
                    );
    

    但在我看来,这项任务有点复杂。

    我也不知道,怎么做 GreaterThan 和 LessThen 采用这种方法:/

    编辑: 现在它也适用于大于和小于

    // Greater Than >
    expression = Expression.GreaterThan(Expression.MakeMemberAccess(member, typeof(DateTime).GetMember("Date").Single()), constant);
    
    // Less Than <
    expression = Expression.LessThan(Expression.MakeMemberAccess(member, typeof(DateTime).GetMember("Date").Single()), constant);
    
    // Equal
    expression = Expression.Equal(Expression.MakeMemberAccess(member, typeof(DateTime).GetMember("Date").Single()), constant);