2016-05-24 8 views
2

多くの箇所で使用されているロジックを、SQLのコンテキストで再利用、集中管理、実行できる式に変換しようとしていますサーバ。Entity Frameworkのコードコレクションで子コレクションに式を作成する方法

これは、式を渡すことによって、EFコンテキストで直接テーブルにクエリを実行するときに実行できます。私が持っている問題は、EFコードファーストでICollectionとして表現されているので、テーブルの子コレクションでこれを実行しようとしています。

コードファーストで定義された簡単な例のテーブル。

public class Table 
{ 
    public int TableId { get; set; } 
    public virtual ICollection<ChildTable> Children { get; set; } 
} 

どのように私はそれをクエリしたいのですか?

var records = context 
    .Table 
    .Select(table => new 
    { 
     ChildRecordCount = table.Children.Count(child => !child.IsArchived), // This works. 
     AltChildRecordCount = table.Children.Count(HowToExpressThisInCSharp()),// Cannot fathom how to do this. 
    }); 

(SQLは、私のC#メソッドの何も知らない)私はのFuncを返す様々な方法(下記参照)を試みたが、彼らは、私はそれを期待するようEFが失敗する原因。では、より簡単なインラインメソッドは式ツリーにどのように変換されますか(SQL Serverに対して実行されるのがわかります)

+1

問題と可能な解決策は、ここで説明されているhttp://www.albahari.com/nutshell/linqkit.aspx –

+0

@IvanStoevおかげで、私はLinqKitを忘れ、それはそうです理想的。私は答えとしてマークすることができますようにあなたのコメントを回答として追加できますか? –

答えて

1
static Func<Menu, bool> HowToExpressThisInCSharp() 
    { 
     return x => !x.IsArchived; 
    } 

問題は、問題の式は式ツリー(table => new { ... })の一部であり、ちょうど従って、実行時にサポートされていない例外を発生させ、内部の「記録」されることです。一般的に、LINQ to Entitiesは式の合成を気に入らず、コンパイル時に解決される「フラット」式を使用する必要があります。

この問題はLINQKitで扱われ、Compile/Expand(より一般的にはAsExpandable)です。シナリオに適用すると、次のようになります。

static Expression<Func<Menu, bool>> HowToExpressThisInCSharp() 
{ 
    return x => !x.IsArchived; 
} 

var criteria = HowToExpressThisInCSharp(); 
var records = context 
    .Table 
    .AsExpandable() 
    .Select(table => new 
    { 
     ChildRecordCount = table.Children.Count(child => !child.IsArchived), 
     AltChildRecordCount = table.Children.Count(criteria.Compile()), 
    }); 
3

Queryable.AsQueryable拡張メソッドを使用します。あなたのユースケースに合わせてください。

static Expression<Func<Menu, bool>> HowToExpressThisInCSharp() 
{ 
    return x => !x.IsArchived; 
} 

var records = context 
.Table 
.Select(table => new 
{ 
    ChildRecordCount = table.Children.Count(child => !child.IsArchived), // This works. 
    AltChildRecordCount = table.Children.AsQueryable().Count(HowToExpressThisInCSharp()), // this works too :) 
}); 
関連する問題