LINQ2SQL Expression - Конвертация не удалась при конвертации даты - PullRequest
0 голосов
/ 29 октября 2018

У меня есть это выражение 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; }
    }

Пожалуйста, не могли бы вы объяснить, в чем здесь проблема?

Edit:

Вместо 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 Ответ

0 голосов
/ 30 октября 2018

это работает, я скопировал его из этого 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);
...