【问题标题】:LINQ2SQL Expression - Conversion failed when converting dateLINQ2SQL 表达式 - 转换日期时转换失败
【发布时间】:2018-10-29 13:25:32
【问题描述】:

我有这个 Linq 表达式

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.Call 与CompareTo 方法一起使用,而不是Express.Equal。

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”

【问题讨论】:

  • 你的 lambda 中 x 的类型是什么? DatePredicate中的“x”是什么类型?
  • @NetMage 我更新了我的问题,这是一个简单的类,只有属性。
  • 你用过LINQPad吗?稍微清理一下,您的代码就可以在 MS SQL Server 上正常工作。使用DataPredicate时生成的SQL到底是什么?

标签: c# lambda linq-to-sql


【解决方案1】:

查看我在这篇帖子here的回答

解决方案是如何让EntityFramework生成带参数的SqlCommand,以便Data Type Mapping可以将CLR DateTime转换为SQL Server等价物。

【讨论】:

    【解决方案2】:

    这个作品,我从这个有 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      相关资源
      最近更新 更多