首页 文章

C# - 动态Linq - 通用搜索 - DateTime

提问于
浏览
2

大家早上好,我有一个关于linq到sql的问题 . 特别是“动态Linq” . 我正在尝试创建一个搜索功能,用户可以在其中输入任何字符串,并过滤所有字段,包括DateTime字段 .

所以说DateTime存储的是“10/11/2015”,当用户键入“10”时我希望记录返回 .

所以类似于:

x=> x.dateTime.ToString("dd/mm/yyyy").Contains("10")

但这不起作用,因为sql没有ToString方法 .

为了使这个问题更有趣,所有这些都是通用的 . 所以我收到必须作为字符串列表搜索的属性,我收到类型为T,我收到搜索字符串作为字符串 .

因此,如果我只是在属性“dateTime”中查找“10”,即如果T是泛型类型,那么我将如何编写搜索表达式 .

ConstantExpression searchArgument = Expression.Constant("10");
ParameterExpression param = Expression.Parameter(typeof(T), "x");

// Get Property, even if nested property.
Expression property = "dateTime".Split('.').Aggregate<string, Expression>(param, Expression.Property);

// Get Contains method for property type
MethodInfo containsMethod = typeof(String).GetMethod("Contains");

// Convert the property if necessary.
MethodInfo convertMethod = null;
if (TypeExtensions.IsNumericType(property.Type))
{
    convertMethod = typeof(SqlFunctions).GetMethod("StringConvert", new[] { typeof(double?) });
    if (convertMethod != null)
    {
        property = Expression.Call(convertMethod, Expression.Convert(property, typeof(double?)));
    }
}
else if (property.Type == typeof(DateTime))
{
    throw new NotImplementedException();
    // TODO - How do I write a convertion method here to convert the DateTime property to a string as "dd/mm/yyyy"?
    convertMethod = null;
    if (convertMethod != null)
    {
        property = Expression.Call(convertMethod, Expression.Convert(property, typeof(DateTime?)));
    }
}

MethodCallExpression fieldExpression = Expression.Call(property, containsMethod, searchArgument);

// Create the contains expression
Expression<Func<T, bool>> searchExpression = Expression.Lambda<Func<T, bool>>(fieldExpression, param);

这适用于字符串和数字但不适用于DateTimes,任何人都可以帮忙吗?提前致谢!

2 回答

  • 0

    我需要对此进行双重检查,但根据https://msdn.microsoft.com/en-us/library/bb738681.aspxDayMonthYear 应该可以正常工作,因此您可以执行以下操作:

    (x.dateTime.Day.ToString().Contains("10") || 
     x.dateTime.Month.ToString().Contains("10") ||
     x.dateTime.Year.ToString().Contains("10"))
    

    我记得EF在整数上理解 ToString() ,虽然我'm not sure, but if it doesn',上面使用 SqlFunctions.StringConvert ,而不是 ToString()


    或者你可以使用 SqlFunctions 而不是调用 ToString 自己创建字符串,类似于:

    (SqlFunctions.DateName("dd", x) + "/" +
     SqlFunctions.StringConvert((double)SqlFunctions.DatePart("m", x)).Trim() + "/" +
     SqlFunctions.DateName("yyyy", x)
    ).Contains("10")
    
  • 1

    您还可以按组件进行比较,检查日,月或年是否等于您传递的变量 . 我不知道你是否也愿意 . 例如,如果用户像“1”那样返回所有日期包含1的记录,但我也不建议,如果你的数据库有一些维度,你会返回很多记录

相关问题