EF6 IQueryable dynamic linq其中(谓词,值)与DbFunctions.TruncateTime

时间:2016-01-13 09:10:26

标签: sql-server entity-framework-6 dynamic-linq

在我的简化示例中,我有一个具有以下属性的对象:

  • 姓名(字符串)
  • BirthDateTimeStamp(datetime)

我需要能够以下列方式构建动态查询

var predicate = "Name = @0";
var values = new object[]{"Ed"};
myIQueryableDataSource.Where(predicate, values)

这项工作很好。现在我想比较我的日期时间

var predicate = "BirthDateTimeStamp >= @0";
var values = new object[]{someDateTime};

这也很好用。但是在比较日期时间时我真正想要做的就是这个问题在做等于比较日期时表现得更好。

var predicate = "BirthDateTimeStamp.Date >= @0";

由于EF to SQL server

无法识别Date属性,因此无法执行此操作
var predicate = "System.Data.Entity.DbFunctions.TruncateTime(BirthDateTimeStamp) >= @0";

这也无效,因为我只能在谓词中访问我的对象属性。

我如何以这种方式解决这个问题,以便谓词保持字符串格式。这段代码只是我查询的一个大型现有解析器的一部分,并且可以完全重写。

2 个答案:

答案 0 :(得分:0)

请参阅https://stackoverflow.com/a/26451213/525788

System.Linq.Dynamic正在解析您作为C#提供的表达式,但不识别类DbFunctions。但是,您可以将DbFunctions作为预定义类型进行修补:

var type = typeof( DynamicQueryable ).Assembly.GetType( "System.Linq.Dynamic.ExpressionParser" );

FieldInfo field = type.GetField( "predefinedTypes", BindingFlags.Static | BindingFlags.NonPublic );

Type[] predefinedTypes = (Type[])field.GetValue( null );

Array.Resize( ref predefinedTypes, predefinedTypes.Length + 1 );
predefinedTypes[ predefinedTypes.Length - 1 ] = typeof( DbFunctions );

field.SetValue( null, predefinedTypes );

然后你可以使用

var predicate = "DbFunctions.TruncateTime(BirthDateTimeStamp) >= @0";

答案 1 :(得分:0)

@RockResolve给出的答案确实奏效了,但是它是一种黑客攻击。 Linq Dynamics提供添加自定义功能的功能

public class CustomTypeProvider: IDynamicLinkCustomTypeProvider
{
    public HashSet<Type> GetCustomTypes()
    {
      HashSet<Type> types = new HashSet<Type>();
      // adding custom types
      types.Add(typeof(DbFunctions)); 
      return types;
    }
}

// use below line to add this to linq
System.Linq.Dynamics.GlobalConfig.CustomTypeProvider = new CustomTypeProvier();