その場で式を組み合わせることができるLinqKitライブラリを使用しています 。
これは、エンティティFramewokデータアクセスレイヤーを作成するための純粋な至福です。複数の式をオプションで再利用および結合できるため、読み取り可能で効率的なコードの両方が可能になります。
次のコードを検討してください。
private static readonly Expression<Func<Message, int, MessageView>> _selectMessageViewExpr =
( Message msg, int requestingUserId ) =>
new MessageView
{
MessageID = msg.ID,
RequestingUserID = requestingUserId,
Body = ( msg.RootMessage == null ) ? msg.Body : msg.RootMessage.Body,
Title = ( ( msg.RootMessage == null ) ? msg.Title : msg.RootMessage.Title ) ?? string.Empty
};
Message
投影する式を宣言しますMessageView
(わかりやすくするために詳細を削除しました)。
これで、データアクセスコードはこの式を使用して個々のメッセージを取得できます。
var query = CompiledQueryCache.Instance.GetCompiledQuery(
"GetMessageView",
() => CompiledQuery.Compile(
_getMessagesExpr
.Select( msg => _selectMessageViewExpr.Invoke( msg, userId ) ) // re-use the expression
.FirstOrDefault( ( MessageView mv, int id ) => mv.MessageID == id )
.Expand()
)
);
まったく同じ式をメッセージリストの取得にも再利用できるため、これはすばらしいことです。
var query = CompiledQueryCache.Instance.GetCompiledQuery(
"GetMessageViewList",
() => CompiledQuery.Compile(
BuildFolderExpr( folder )
.Select( msg => _selectMessageViewExpr.Invoke( msg, userId ) )
.OrderBy( mv => mv.DateCreated, SortDirection.Descending )
.Paging()
.Expand()
),
folder
);
ご覧のとおり、射影式はに格納され_selectMessageViewExpr
、いくつかの異なるクエリを作成するために使用されます。
ただし、このコードがExpand()
呼び出し時にクラッシュするという奇妙なエラーの追跡に多くの時間を費やしました。
エラーは言った:
System.Linq.Expressions.FieldExpression
タイプのオブジェクトをタイプにキャストできませんSystem.Linq.Expressions.LambdaExpression
。
式が呼び出される前にローカル変数で参照されると、すべてが機能するInvoke
ことに気付いたのはしばらくしてからです。
var selector = _selectMessageViewExpr; // reference the field
var query = CompiledQueryCache.Instance.GetCompiledQuery(
"GetMessageView",
() => CompiledQuery.Compile(
_getMessagesExpr
.Select( msg => selector.Invoke( msg, userId ) ) // use the variable
.FirstOrDefault( ( MessageView mv, int id ) => mv.MessageID == id )
.Expand()
)
);
このコードは期待どおりに機能します。
私の質問は:
Invoke
LinqKitがフィールドに格納された式を認識しない特定の理由はありますか?それは開発者による単なる省略ですか、それとも式を最初にローカル変数に格納する必要がある重要な理由がありますか?
この質問は、生成されたコードを調べてLinqKitソースを確認することでおそらく答えることができますが、LinqKit開発に関係する誰かがこの質問に答えることができるのではないかと思いました。
ありがとう。