web-dev-qa-db-ja.com

内部.NET Frameworkデータプロバイダーエラー1025

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ステートメントを使用できないことを知っているため、デリゲートをパラメーターとして渡します。

最初のクエリを機能させるにはどうすればよいですか?

54
Freshblood

上記の答えは正しいですが、selectステートメントの後に使用する場合は、AsQueryable()を明示的に呼び出す必要があります。そうしないと、コンパイラーは、Funcを期待するIEnumerableメソッドを使用しようとしていると想定しますExpression<Func>ではありません。

これはおそらく、元のポスターの問題でした。さもないと、コンパイラは、FuncではなくExpression<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()
35
yoel halb

報奨金(ラット!)を作成した後、 この答え が見つかりました。これで問題が解決しました。 (私の問題には.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<Func<Reservation, bool>>の別のメソッドを直接参照することはできません。

25
Shaul Behr

Pingを送ってくれてありがとう。結局、私は正しい軌道に乗っていたと思います。

とにかく、繰り返しになりますが、 LINQ to Entities (コメントで自分の思考プロセスに混乱が生じたときに修正してくれたJon Skeetに感謝します)は Expression Trees ; QueryProviderでラムダ式をSQLに変換する投影 が許可されます。

レギュラーFunc<>は、 LINQ to Objects。

したがって、この場合、Entity Frameworkを使用しているときは、EFのIQueryableに渡される述語はすべてExpression<Func<>>

19
Patryk Ćwiek

別のシナリオでこの問題を経験しました。

Expression述語でいっぱいの静的クラスがあり、これを組み合わせてEFクエリに渡すことができます。それらの1つは:

_    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エラーをスローしていました。エンティティフレームワークはExpressionを予期していましたが、method groupを検出したため、エラーが発生しました。ラムダ(暗黙的に式にキャストできる)を使用するようにコードを変換すると、エラーが修正されました。

_    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 => ce.Event.AttendeeStatuses.Any(a => a.ClientId == ce.Client.Id && statuses.Contains(a.Status.Value));に簡略化しました

5
AlexFoxGill

同様の問題がありました。次のような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();

2番目の.Selectは混乱であるため、最初の1つは実際にはICollectionから呼び出されますが、これはIQueryableではないため、最初のExpressionをExpression<Func...ではなくプレーンなFuncとして消費します。このページで説明したように、それはIEnumerable<...を返します。 .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();

しかし、それは新しい、奇妙な問題を作成します:内部フレームワーク...エラー1025を取得するか、.Postプロパティが完全にロードされたpost変数を取得しますが、.TagsプロパティにはLazy-読み込み中。

解決策は、匿名クラスの使用を終了することにより、タグの戻り値の型を制御することです。

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();
0
Chris Moschini