内部.NET Framework数据提供程序错误1025

Fre*_*ood 55 .net c# entity-framework expression-trees entity-framework-4

IQueryable<Organization> query = context.Organizations;

Func<Reservation, bool> predicate = r => !r.IsDeleted;

query.Select(o => new { 
    Reservations = o.Reservations.Where(predicate)
}).ToList();
Run Code Online (Sandbox Code Playgroud)

此查询引发"内部.NET Framework数据提供程序错误1025"异常,但下面的查询不会.

query.Select(o => new { 
    Reservations = o.Reservations.Where( r => !r.IsDeleted)
}).ToList();
Run Code Online (Sandbox Code Playgroud)

我需要使用第一个,因为我需要检查一些if语句来构造正确的谓词.我知道在这种情况下我不能使用if语句,这就是我将委托作为参数传递的原因.

如何使第一个查询起作用?

yoe*_*alb 37

虽然上面的答案都是正确的,但请注意,当在select语句之后尝试使用它时,必须AsQueryable()显式调用,否则编译器将假定我们正在尝试使用IEnumerable方法,它们期望a Func而不是Expression<Func>.

这可能是原始海报的问题,否则编译器会在大多数情况下抱怨它正在寻找Expression<Func>而不是Func.

演示:以下内容将失败:

MyContext.MySet.Where(m => 
      m.SubCollection.Select(s => s.SubItem).Any(expr))
         .Load()
Run Code Online (Sandbox Code Playgroud)

虽然以下内容有效:

MyContext.MySet.Where(m => 
      m.SubCollection.Select(s => s.SubItem).AsQueryable().Any(expr))
         .Load()
Run Code Online (Sandbox Code Playgroud)


Sha*_*ica 25

创造赏金(老鼠!)之后,我找到了这个答案,这解决了我的问题.(我的问题涉及一个.Any()电话,这比这个问题复杂一点......)

简而言之,这是你的答案:

IQueryable<Organization> query = context.Organizations;

Expression<Func<Reservation, bool>> expr = r => !r.IsDeleted;

query.Select(o => new { Reservations = o.Reservations.Where(expr) })
  .ToList();
Run Code Online (Sandbox Code Playgroud)

阅读引用的答案以解释为什么需要局部变量expr,并且不能直接引用另一种返回类型的方法Expression<Func<Reservation, bool>>.


Pat*_*iek 19

谢谢你对我说话.我想我毕竟是在正确的轨道上.

无论如何,重申一下,LINQ to Entities(感谢Jon Skeet在我在评论中混淆了我自己的思考过程时纠正了我)在Expression Trees上运行 ; 它允许投影将lambda表达式转换为SQLQueryProvider.

常规Func<>适用于LINQ to Objects.

所以在这种情况下,当你使用实体框架时,任何传递给EF的谓词IQueryable都必须是Expression<Func<>>.

  • 我已经在上面评论了 Func&lt;&gt; delegate 和 Expression&lt;&gt; 参数。如果您再次查看这行代码 Reservations = o.Reservations.Where(predicate) 您将意识到 o.Reservations 是 ICollection&lt;&gt; 而不是 IQueryable&lt;&gt;,因为它只是导航属性。其上的任何Where 扩展方法都是IEnumerable&lt;&gt; 扩展。因此传递 Func&lt;&gt; 委托而不是 Expression&lt;&gt; 是正确的。 (2认同)

Ale*_*ill 5

我刚刚在不同的场景中遇到过这个问题.

我有一个充满Expression谓词的静态类,然后我可以将它组合或传递给EF查询.其中一个是:

    public static Expression<Func<ClientEvent, bool>> ClientHasAttendeeStatus(
        IEnumerable<EventEnums.AttendeeStatus> statuses)
    {
        return ce => ce.Event.AttendeeStatuses
            .Where(a => a.ClientId == ce.Client.Id)
            .Select(a => a.Status.Value)
            .Any(statuses.Contains);
    }
Run Code Online (Sandbox Code Playgroud)

由于Contains方法组调用,这导致了1025错误.实体框架期望一个Expression并找到一个方法组,导致错误.转换代码以使用lambda(可以隐式转换为Expression)修复了错误

    public static Expression<Func<ClientEvent, bool>> ClientHasAttendeeStatus(
        IEnumerable<EventEnums.AttendeeStatus> statuses)
    {
        return ce => ce.Event.AttendeeStatuses
            .Where(a => a.ClientId == ce.Client.Id)
            .Select(a => a.Status.Value)
            .Any(x => statuses.Contains(x));
    }
Run Code Online (Sandbox Code Playgroud)

旁白:然后我将表达式简化为 ce => ce.Event.AttendeeStatuses.Any(a => a.ClientId == ce.Client.Id && statuses.Contains(a.Status.Value));