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

Posted

技术标签:

【中文标题】内部 .NET Framework 数据提供程序错误 1025【英文标题】:Internal .NET Framework Data Provider error 1025 【发布时间】:2012-08-12 23:30:14 【问题描述】:
IQueryable<Organization> query = context.Organizations;

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

query.Select(o => new  
    Reservations = o.Reservations.Where(predicate)
).ToList();

此查询会引发“Internal .NET Framework Data Provider error 1025”异常,但下面的查询不会。

query.Select(o => new  
    Reservations = o.Reservations.Where( r => !r.IsDeleted)
).ToList();

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

我怎样才能使第一个查询工作?

【问题讨论】:

我不完全确定这是否是原因(甚至是正确的方向),但Linq2Objects 在表达式树上运行,这意味着您通常通过Expression&lt;Func&lt;Reservation, bool&gt;&gt; predicate 而不是裸Func&lt;Reservation, bool&gt; predicate .你可以随时尝试。 :) 听起来您可能需要一个谓词构建器。看看这个问题。 ***.com/questions/9184942/… @Trustme-I'maDoctor:你错了 - LINQ to Objects 使用委托。它是使用表达式树的 LINQ to SQL 等,因为它们需要将查询转换为 SQL。 LINQ to Objects 可以直接执行谓词、项目等。 @JonSkeet 绝对是,但很好区分。我有时会忘记,并非您使用 LINQ 的所有集合都以某种方式受数据库支持 :) 在完全不相关的旁注中,您的书是一本很棒的书,我想在接下来的几本书中我会做更多的阅读未来几周。 @JonSkeet - 我得到的行为与 OP 完全相同,除了我将谓词抽象为静态方法,因为我在很多地方都使用它。我不想将谓词复制并粘贴到所有使用它的地方。解决办法是什么? 【参考方案1】:

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

这可能是原始海报的问题,否则编译器大部分时间都会抱怨它正在寻找Expression&lt;Func&gt;而不是Func

演示: 以下将失败:

MyContext.MySet.Where(m => 
      m.SubCollection.Select(s => s.SubItem).Any(expr))
         .Load()

虽然以下方法可行:

MyContext.MySet.Where(m => 
      m.SubCollection.Select(s => s.SubItem).AsQueryable().Any(expr))
         .Load()

【讨论】:

感谢您完成答案。拯救了我的一天! 这甚至适用于嵌套投影 (.Include)。干得好! 这对我帮助很大。我的问题正是因为直接使用表达式导致 IEnumerable 重载被调用。【参考方案2】:

创建赏金(老鼠!)后,我找到了this answer,这解决了我的问题。 (我的问题涉及到.Any() 电话,比这个问题要复杂一些……)

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

IQueryable<Organization> query = context.Organizations;

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

query.Select(o => new  Reservations = o.Reservations.Where(expr) )
  .ToList();

阅读引用的答案,了解为什么需要局部变量 expr,并且不能直接引用返回类型为 Expression&lt;Func&lt;Reservation, bool&gt;&gt; 的另一种方法。

【讨论】:

在我看来,这与16日“相信我-我是医生”提供的建议相同。也许他应该得到赏金?【参考方案3】:

感谢您对我的 ping 操作。我想我毕竟是在正确的轨道上。

无论如何,重申一下,LINQ to Entities(感谢 Jon Skeet 在我在 cmets 中混淆了自己的思维过程时纠正了我)在 Expression Trees 上运行;它允许projection to translate the lambda expression to SQL by the QueryProvider

普通的Func&lt;&gt; 适用于LINQ to Objects.

因此,在这种情况下,当您使用实体框架时,传递给 EF 的 IQueryable 的任何谓词都必须是 Expression&lt;Func&lt;&gt;&gt;

【讨论】:

我收到了关于 Func 委托和 Expression 参数的正面评论。如果您再次查看这行代码 Reservations = o.Reservations.Where(predicate) 您会意识到 o.Reservations 是 ICollection 而不是 IQueryable 因为它只是导航属性。其上的任何 Where 扩展方法都是 IEnumerable 扩展。所以传递 Func 委托而不是 Expression 是正确的。【参考方案4】:

我只是在不同的场景中遇到了这个问题。

我有一个充满 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);
    

这是由于 Contains 方法组调用而引发的 1025 错误。实体框架需要一个表达式并找到一个方法组,导致错误。将代码转换为使用 lambda(可以隐式转换为表达式)修复了错误

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

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

【讨论】:

【参考方案5】:

遇到了类似的问题。如下所示的 ViewModel 库:

public class TagViewModel

    public int Id  get; set; 
    public string Name  get; set; 

    public static Expression<Func<SiteTag, TagViewModel>> Select = t => new TagViewModel
    
        Id = t.Id,
        Name = t.Name,
    ;

这行得通:

var tags = await db.Tags.Take(10).Select(TagViewModel.Select)
    .ToArrayAsync();

但是,这不会编译:

var post = await db.Posts.Take(10)
    .Select(p => new 
        Post = p,
        Tags = p.Tags.Select(pt => pt.Tag).Select(TagViewModel.Select)
    )
    .ToArrayAsync();

因为第二个.Select 是一团糟——第一个实际上是从 ICollection 中调用的,它不是 IQueryable,所以它将第一个表达式作为普通的 Func 使用,而不是 Expression&lt;Func...。如本页所述,返回 IEnumerable&lt;...。所以.AsQueryable()来救援:

var post = await db.Posts.Take(10)
    .Select(p => new 
        Post = p,
        Tags = p.Tags.Select(pt => pt.Tag).AsQueryable()
            .Select(TagViewModel.Select)
    )
    .ToArrayAsync();

但这会产生一个新的、更奇怪的问题:要么我得到 Internal Framework...Error 1025,要么我得到带有完全加载的 .Post 属性的 post 变量,但 .Tags 属性有一个 EF 代理对象似乎用于延迟加载。

解决办法是控制标签的返回类型,结束使用匿名类:

public class PostViewModel

    public Post Post  get; set; 
    public IEnumerable<TagViewModel> Tags  get; set; 

现在选择这个,一切正常:

var post = await db.Posts.Take(10)
    .Select(p => new PostViewModel 
        Post = p,
        Tags = p.Tags.Select(pt => pt.Tag).AsQueryable()
            .Select(TagViewModel.Select)
    )
    .ToArrayAsync();

【讨论】:

以上是关于内部 .NET Framework 数据提供程序错误 1025的主要内容,如果未能解决你的问题,请参考以下文章

将 func 作为 Linq 中的参数传递给实体和“内部 .NET Framework 数据提供程序错误 1025”错误

找不到请求的 .Net Framework 数据提供程序

.NET Framework概述

VS2010:“找不到请求的 .NET Framework 数据提供程序”

从 Windows 通过 Entity Framework 连接到 Informix 的问题

跨 Asp.NET Core 和 Framework 的数据保护提供程序(生成密码重置链接)