2

クラスを再利用できるように、いくつかのラムダ式を使用して型から値を選択するジェネリック型クラス Filter があります。そのクラスは別のジェネリック型クラス Search で使用されます。Search は Filter を使用して、最終的にドロップダウン リストで使用される型の個別の項目を選択します。

これらの重要でないコードを削除しました。

public class Filter<T>
{
   public string Name;
   public Func<T, string> Key;
   public Func<T, string> Value;
}

public class Search<T>
{
   MyDBContext db = new MyDBContext();
   IQueryable<T> Model = db.Stuff.OrderBy(a => a.TermID);
   Filter filter = new Filter(
      Name: "Term",
      Value: a => a.TermID.ToString(),
      Key: a => a.Term.TermType.Name
   );

   var filterItems = Model
      .Select(a => new { Key = filter.Key(a), Value = filter.Value(a)})
      .OrderBy(t => t.Key)
      .Distinct()
      .ToArray();
}

実行時エラーが発生します。The LINQ expression node type 'Invoke' is not supported in LINQ to Entities. 匿名型の代わりに強力な型を使用してExpression<Func<T,string>>、フィルターで使用しようとしました。

何時間も検索してさまざまなことを試した後、これを機能させる方法がわかりません。ご協力ありがとうございました。

4

1 に答える 1

0

あなたの問題はもっと簡単に表現できます。例えば、これはそれを再現します:

Func<SomeClass, int> x = t => t.ID;
var y = db.SomeClasses.Select(c => x(c)).ToArray();

正常にコンパイルされますが、コンパイルされた関数を呼び出しているため、実行時に同じエラーが発生します。その部分「t => t.ID」は(少なくともILに)コンパイルされたコードであり、linqはこれを読み取ってSQLに変換できません。式ツリーを SQL に変換することしかできません。上記のケースの解決策はかなり単純です。これがあなたの状況にどのように変換されるかはわかりませんが、可能であるはずです.

Expression<Func<SomeClass, int>> x = t => t.ID;
var y = db.SomeClasses.Select(x).ToArray();

また、関数呼び出しを linq からオブジェクトに移動して、SQL に変換する必要がないようにするオプションもあります (「AsEnumerable」以降のすべてがクライアントで処理されます)。これにより、関数に配置できる内容の柔軟性が大幅に向上し、発生するエラーの種類がなくなります。これにより、SqlFunctions を呼び出す必要もなくなります (以下を参照)。欠点は、サーバーから必要以上の行が返される可能性があることです。

Func<SomeClass, int> x = t => t.ID;
var y = db.SomeClasses.AsEnumerable().Select(c => x(c)).ToArray();

あなたの最後の問題は、EF が ToString メソッドを好まないことであり、かなりくだらない SqlFunctions.StringConvert を使用する必要があります。ここを参照してください: Entity Framework の int から文字列へ

于 2012-07-24T03:53:05.677 に答える