7

次の Entity Framework クエリはエラーなしで実行されます。

Predicate<Program> filterProgram;
if (programId.HasValue)
    filterProgram = (p => p.Id == programId && !p.IsDeleted);
else
    filterProgram = (p => !p.IsDeleted);

var analytics = (from a in repository.Query<Analytic>()
                 where (a.Marker == "Open" || a.Marker == "LastTouch") &&
                 a.EntityType == "Proposal" &&
                 a.Site == "C"
                 join p in repository.Query<Program>()
                 on a.EntityId equals p.Id
                 //where filterProgram(p)
                 group a
                 by new { a.LoginSessionId, a.EntityId, p.Id, p.Name } into g
                 let f = g.OrderBy(x => x.TimestampUtc).FirstOrDefault(x => x.Marker == "Open")
                 where f != null
                 let t = g.FirstOrDefault(x => x.Marker == "LastTouch" && x.TimestampUtc > f.TimestampUtc)
                 select new
                 {
                     ProgramId = g.Key.Id,
                     Program = g.Key.Name,
                     ProposalId = g.Key.EntityId,
                     FirstOpen = f,
                     LastTouch = (t ?? f).TimestampUtc
                 }).ToList();

ただし、行のコメントを外すとwhere filterProgram(p)、実行時エラーが発生します。

LINQ 式ノード タイプ 'Invoke' は、LINQ to Entities ではサポートされていません。

私は、LINQ が述語をクエリに組み込み、それを SQL に変換できることを期待していました。このエラーが発生するのはなぜですか? この方法で where 述語を動的に変更する方法はありますか?

4

4 に答える 4

2

filterProgramの型を に変更するExpression<Func<Program, bool>>と、LINQ Where 句で使用できるようになります。

ただし、注意点が 1 つあります。メソッド チェーン構文では機能するようになりましたが、クエリ構文では機能しませんでした。

たとえば、これは機能します:

dataContext.Programs.Where (filterProgram)

しかし、これはしません:

from p in dataContext.Programs
where filterprogram 

Where(コンパイラは、 と の両方で利用可能なIEnumerableメソッドを解決できないと文句を言いますIQueryable。)

あなたの場合、行を置き換えることは許容されるかもしれません

join p in repository.Query<Program>()

join p in repository.Query<Program>().Where(filterProgram)
于 2013-01-30T08:06:58.510 に答える
1

問題は、linq2entities が式ツリーを SQL に変換しようとすることです。式ツリーにはInvokeデリゲート型 (filterProgram) でメソッドの呼び出しがありますが、その述語をインライン化することを止めるものは何もありません。

var id= programId.HasValue ? programId.GetValueOrDefault() : -1;
var analytics = (from a in repository.Query<Analytic>()
                 where (a.Marker == "Open" || a.Marker == "LastTouch") &&
                 a.EntityType == "Proposal" &&
                 a.Site == "C"
                 join p in repository.Query<Program>()
                 on a.EntityId equals p.Id
                 where !p.IsDeleted && (!hasValue || p.Id == id)
                 ....

これは、-1 が無効な programId であることを前提としています

于 2013-01-30T08:07:08.300 に答える
1

Linq to Entities では、クエリを に変換せずに外部メソッドを呼び出すことはできませんIEnumerable。したがって、filterProgramはメソッドであるため、クエリ内で呼び出すことはできません。

可能であればToList、 を呼び出す前に呼び出すことができますFilterProgram。別のオプションとして、のロジックをfilterProgramクエリに挿入することもできます。

于 2013-01-30T07:38:34.940 に答える