【问题标题】:EF6 IQueryable dynamic linq Where(predicate, values) with DbFunctions.TruncateTimeEF6 IQueryable 动态 linq Where(predicate, values) with DbFunctions.TruncateTime
【发布时间】:2016-01-13 09:10:25
【问题描述】:

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

  • 名称(字符串)
  • BirthDateTimeStamp(日期时间)

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

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

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

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

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

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

这是不可能的,因为 EF 无法将 Date 属性识别到 SQL 服务器

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

这也不起作用,因为我只能在谓词中访问我的对象属性。

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

【问题讨论】:

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


    【解决方案1】:

    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";
    

    【讨论】:

      【解决方案2】:

      @RockResolve 给出的答案确实有效,但有点像 hack。 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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-29
        • 2015-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多