C# LINQ to实体不支持扩展方法?

C# LINQ to实体不支持扩展方法?,c#,linq,entity-framework,linq-to-entities,C#,Linq,Entity Framework,Linq To Entities,我有两种像这样的扩展方法 public static IQueryable<T> CurrentVersion(this IQueryable<T> queryable, DateTime date) { return queryable.Where(p => p.CreationDate>date); } public static IEnumerable<T> CurrentVersion(this IEnum

我有两种像这样的扩展方法

  public static IQueryable<T> CurrentVersion(this IQueryable<T> queryable, DateTime date)
  {
        return queryable.Where(p => p.CreationDate>date);
  }

  public static IEnumerable<T> CurrentVersion(this IEnumerable<T> queryable, DateTime date)
  {
        return queryable.Where(p => p.CreationDate>date);
  }
但当我在流动查询中使用它时,我得到了一个错误

 var q = Db.Groups.SelectMany(p => p.GroupMembers.AsQueryable().CurrentVersion(date));

OR

 var q = Db.Groups.SelectMany(p => p.GroupMembers.AsEnumerable().CurrentVersion(date));

 var result = q.ToList();    // Here I get error
错误:

LINQ to实体无法识别方法“System.LINQ.IQueryable
1[…](System.LINQ.IQueryable
1[…,System.DateTime)”方法,并且无法将此方法转换为存储表达式

现在我有两个问题:

  • 我在谷歌上搜索了这个错误,发现了许多与我在stackoverflow中的问题相同的问题。所有答案都是“Linq to Entities无法将此扩展方法转换为SQL查询”。现在如果有人帮助我,我将不胜感激,为什么我的第一个查询没有出现任何错误

  • 如何将Linq可以识别的扩展方法更改为实体


  • Linq查询需要转换为sql。当您的CurrentVersion扩展名为inline时,如下所示:

    Db.Groups.CurrentVersion();
    
    public static Expression<T, bool> CurrentVersion( DateTime date)
    {
        return p => p.CreationDate > date;
    }
    
    var q =  Db.Groups.Where(ExpressionsHelper.CurrentVersion(date));
    ...
    Expression<T, bool> filterExpression = ExpressionsHelper.CurrentVersion(date);
    Db.Groups.SelectMany(p => p.GroupMembers.AsQueryable().Where(filterExpression));
    
    然后EF只调用CurrentVersion方法,获取结果IQueryable对象,并将其转换为查询。另一方面,对于该查询:

    var q = Db.Groups.SelectMany(p => p.GroupMembers.AsQueryable().CurrentVersion(date));
    
    SelectMany中的内部表达式可能永远不会在代码中调用!它是要转换为sql的。因此,它被视为表达式对象,然后进行解析,但在您调用方法时,它包含调用表达式,但由于明显的原因,无法转换为sql。因此,从SelectMany lambda参数中,您可以无法调用任何方法,您必须提供适当的表达式。CurrentVersion方法提供的最有价值的东西是筛选表达式。按如下方式更改您的方法:

    Db.Groups.CurrentVersion();
    
    public static Expression<T, bool> CurrentVersion( DateTime date)
    {
        return p => p.CreationDate > date;
    }
    
    var q =  Db.Groups.Where(ExpressionsHelper.CurrentVersion(date));
    ...
    Expression<T, bool> filterExpression = ExpressionsHelper.CurrentVersion(date);
    Db.Groups.SelectMany(p => p.GroupMembers.AsQueryable().Where(filterExpression));
    
    公共静态表达式CurrentVersion(日期时间日期)
    {
    返回p=>p.CreationDate>date;
    }
    
    可以这样使用它:

    Db.Groups.CurrentVersion();
    
    public static Expression<T, bool> CurrentVersion( DateTime date)
    {
        return p => p.CreationDate > date;
    }
    
    var q =  Db.Groups.Where(ExpressionsHelper.CurrentVersion(date));
    ...
    Expression<T, bool> filterExpression = ExpressionsHelper.CurrentVersion(date);
    Db.Groups.SelectMany(p => p.GroupMembers.AsQueryable().Where(filterExpression));
    
    var q=Db.Groups.Where(expressionHelper.CurrentVersion(日期));
    ...
    表达式filterExpression=ExpressionHelper.CurrentVersion(日期);
    SelectMany(p=>p.GroupMembers.AsQueryable().Where(filterExpression));
    
    如果您希望,您可能仍然让扩展方法与新方法共享过滤逻辑:

    public static IQueryable<T> CurrentVersion(this IQueryable<T> queryable, DateTime date)
    {
        return queryable.Where(ExpressionsHelper.CurrentVersion(date));
    }
    
    公共静态IQueryable CurrentVersion(此IQueryable可查询,日期时间日期)
    {
    返回queryable.Where(expressionHelper.CurrentVersion(日期));
    }
    
    我认为您的扩展与我的扩展方法没有什么不同,因为queryable.Where(expressionHelper.CurrentVersion(date))与queryable.Where(p=>p.CreationDate>date)相等;确实是queryable.Where(expressionHelper.CurrentVersion(date))应该作为queryable.Where(p=>p.CreationDate>date)工作;但这就是目标,对吗?我更改了您的方法,以便在您呼啸时可以重用您的筛选逻辑。因此,区别应该是我提出的方法正在工作,EF可以将其解析为查询。但是我版本的CurrentVersion extension方法不能应用于嵌套查询!您只能在简单查询(如Db.Gr)中使用它ups.CurrentVersion();对于复杂的,您需要使用Db.Groups.SelectMany(p=>p.GroupMembers.AsQueryable()。其中(expressionHelper.CurrentVersion(date)));扩展方法仅作为示例提供-如果您希望拥有它,则可以不使用代码重复。那么我如何实现一个可以在嵌套查询中使用它的方法?请再次仔细查看我的答案:)First write method公共静态表达式CurrentVersion(DateTime date){return p=>p.CreationDate>date;}(不是扩展方法!)。然后使用它Db.Groups.SelectMany(p=>p.GroupMembers.AsQueryable()。其中(expressionHelper.CurrentVersion(date));