2012-04-12 6 views
8

私はデータベーステーブルItemを持っており、linq-to-sqlでアクセスします。非スタティック式<Func<X>> 'this'へのアクセス

私はItem.idの平方根が偶数の場合はtrueを返すアイテムのためのカスタムメソッドIsSpecial()を定義することができます。そして、私は、LINQツーSQLクエリでそのプロパティを使用することができます

partial class Item 
{ 
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0); 
} 

をこのように:

datacontext.Item.Where(i => i.IsSpecial()) 
:美的な理由のために今

datacontext.Item.Where(Item.IsSpecial) 

、私はこのようにそれを呼び出すことができるようにIsSpecialは非静的作り、それを変更したいです

理想的には、これはまた、上記(作業)snytaxが許可しない文、の組み合わせが可能になります。

datacontext.Item.Where(i => i.IsSpecial() && i.Id >100) 

このメソッドを定義するための正しい構文は何ですか?

これは動作しません:

partial class Item 
{ 
    public Expression<Func<bool>> IsSpecial = (() => Math.Sqrt(this.Id)%2==0); 
    // 'this' keyword not available in current context 
} 

編集: 私は私が私ができると思い構文は単に

を許可していない何かを求めていますことを疑い始めていますlive with datacontext.Item.Where(Item.IsSpecial).Where(i => i>100)

+0

ところで 'datacontext.Item。 where(i => Item.IsSpecial(i)) 'はコンパイルされません。 – leppie

+0

IsSpecialメソッドを定義する代わりに、Func型のIsSpecialプロパティを定義するのはなぜですか?またはbool型のIsSpecialプロパティだけでも可能ですか? –

+0

'datacontext.Item.Where(Item.IsSpecial)'がコンパイルされます。 – leppie

答えて

4
partial class Item 
{ 
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0); 
} 

提案:readonlyキーワードを追加します。

それから私はこのようなLINQツーSQLクエリでそのプロパティを使用することができます。WhereItem.IsSpecialがあるタイプExpression<Func<Item, bool>>のパラメータを、受け入れるため、

datacontext.Item.Where(Item.IsSpecial) 

右。

今美的な理由のために、私はIsSpecialは非静的作るので、私はこのようにそれを呼び出すことができ、それを変更したい:

datacontext.Item.Where(i => i.IsSpecial()) 

IsSpecialではないので、これは動作しない理由は、関数、それは式ツリーです。 ()は、関数にのみ適用できます。式ツリーは関数を記述しますが、関数ではありません。あなたはexpression.Compile()を使用して、実際の関数を作成することができます

datacontext.Item.Where(i => (IsSpecial.Compile()) (i)) 

しかし、再び、Whereは、式ツリーを渡され、IsSpecial.Compile()が実際に呼び出されていないため、これは、動作しません。 LINQ to SQLはそれをSQLに変換しようとしますが、それはExpression.Compileを認識しないために失敗し、例外がスローされます。しかし

、SQLにLINQはそれを見ていた前に、あなたが(IsSpecial.Compile())を置き換えることができれば...

LINQKitの出番です:

それはそれは働い取得する式ツリー操作のちょうどそのビットを提供します。

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i)) 

.AsExpandable()はプレフィルタ発現にdatacontext.Itemのラッパーを作成します。

理想的には、これはまた、上記(作業)snytaxを許可しませんステートメント、の組み合わせが可能になります。

datacontext.Item.Where(i => i.IsSpecial() && i.Id >100) 

を問題なし:

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i) && i.Id > 100) 
+0

これは非常に有望で、ありがとう!私はちょうどこれのために別のライブラリを組み込むことについて少し懐疑的ですが、linqkitへのリンクも私にこの問題をより詳細に議論するように思われるhttp://tomasp.net/blog/linq-expand.aspxに導いた – HugoRune

2

直接IsSpecialを使用することができます。

partial class Item 
{ 
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0); 
} 

datacontext.Item.Where(Item.IsSpecial) 
+0

+1実際にコンパイルする最初の解決策。私はしかし、同じことについてコメントをしました:) – leppie

+0

申し訳ありませんが、私の最初の質問で構文をコピーすると、これは私が書こうとしていたものです。理想的には、これを '(NOT VALID :) datacontext.Item.Where(i => i.isSpecial()&& i.Id> 100 && [more properties]'のように変更したいと思います。 – HugoRune

1

IsSpecialへの代入をコンストラクタに入れ、他のすべてのコンストラクタを委譲するか、OnCreatedなどの部分的なメソッドを使用して式をIsSpecialに割り当てることができます。これを行うpartial class Item

partial void OnCreated() 
{ 
    IsSpecial =() => Math.Sqrt(this.Id)%2==0; 
} 

の Insideは、常にIsSpecialを割り当てて、 "これ" へのアクセスを許可します。

+0

この方法で 'this 'を使うことができる限り、これはうまくいきますが、Linqは.Where句の中で使われている式にパラメータを渡すことを主張しているので、xyzは動作しませんそれは(item)=> xyzである必要があります。これは、渡されたパラメータを無視しなければならないことを意味し、全体が乱雑になります。しかし、この提案は、関連する問題を解決するのに非常に役立ったので、ありがとう! – HugoRune

+0

@HugoRune Lookingあなたの前のコメントのいくつかでは、あなたが望むようにコメントの1つとして機能すると思う*(実際にはわかりません): 'datacontext.Item.Where(i => i.IsSpecial() && 私。Id> 100 && [moreプロパティ] ' – JKor

+0

ええ、私もそうだと思っていましたが、これはこの方法では不可能であることが判明しました。 'this'の問題を除いて、これは 'this'の代わりに定数を使用してもまだ動作しません。理由:IsSpecialは式ツリーであり、単純な関数やラムダではありません。 'IsSpecial()'を呼び出すことは有効な構文ではありません。 'I => i.IsSpecial &&.Id> 100'も有効な構文ではないので、このような式ツリーを連結することはできません。混乱することは、式>の代わりに単純なデリゲートまたは関数を使用するとコンパイルされ、通常のLinqで動作しますが、linq-to-SQLは別のビーストです – HugoRune

関連する問題