2

Utility.GetString(MyEntity.SomePropertyWithRelatedEntity)=="abc"(単純化された) のような関数呼び出しを式のビジターに置き換えようとしていますp => p.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag==true).SomePropertyWithRelatedEntity

つまり、データモデルは次のようになります: MyEntity -> RelatedEntity -> SubRelatedEntity

SubRelatedEntityのいくつかのルールに基づいて、から文字列値を返そうとしているRelatedEntityので、使用するたびにフィルタリング ルール全体を書き直したり、コピーしたり、貼り付けたりする必要はありません。そのため、「呼び出し署名」を入れて、式のビジターがそれを識別し、偽の呼び出しをUtility.GetStringいくつかの複雑なラムダ式に置き換えることができるようにします。

私の式ビジターには次のようなものが含まれています:

    public override Expression Visit(Expression node)
    {
        if (node == null)
            return null;

        Expression result = null;

        if (node.NodeType == ExpressionType.Call)
        {
            MethodCallExpression mce = node as MethodCallExpression;
            if (mce.Method.DeclaringType == typeof(Utility) && mce.Method.Name == "GetString")
            {
                Expression<Func<RelatedEntity, string>> exp = re => re.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag == true).SomeStringValue;
                result = exp.Body;

            }
            else
                result = base.Visit(node);
        }
        else
            result = base.Visit(node);

        return result;

    }

ここでの問題は、注入されたラムダ式が呼び出されたときに「sre」パラメーターがバインドされていないことです。多くの調査の結果、ラムダ パラメータを別の式ビジターに置き換える必要があることがわかりました。具体的には、新しいパラメータを検索して古いパラメータに置き換えます。ただし、私の状況では、「古いパラメーター」はありませんMyEntity.SomePropertyWithRelatedEntity。生成されたラムダに何らかの方法で挿入する必要がある式 (関連するエンティティで満たされたプロパティなど) があります。

私の問題が理解できることを願っています。洞察をありがとう!

4

1 に答える 1

3

長い間答えが得られず、解決策を見つけるために一生懸命努力した後、最後に解決しました:o)! こんなふうになります:

新しく挿入されたラムダ式は ParameterExpression を取得します。これは、ラムダを直接呼び出すときに使用される「ヘルパー」であり、望ましくないものです (したがって、ToEnumerable が呼び出されたときに「パラメーターがバインドされていません」という例外が発生します)。したがって、手がかりは、このヘルパーを元の式に置き換える特殊な ExpressionVisitor を作成することです。これは、もちろん、メソッド呼び出しの Arguments[] で使用できます。これを置き換えようとしています。

魔法のように機能します。このように、同じ LINQ 式を再利用できます。再利用可能なサブクエリのようなもので、常に同じ LINQ のものをすべて記述する必要はありません。メソッドを呼び出す式は EF では許可されていないことに注意してください。Linq2Sql では機能しました。また、提案されたすべての Web 記事は、より多くの LINQ 式を一緒に構築/マージするときに、パラメーター インスタンスのみを置き換えるだけです。ここでは、パラメーターを偽のメソッド呼び出し引数に置き換える必要がありました。コード マーカーの場合、LINQ サブクエリを配置する必要があります。

これが誰かの役に立てば幸いです。最終的には、式ツリーがどのように構築されているかを知っていれば、非常にシンプルで論理的です;-)。

さようなら、アンドレイ

于 2012-05-26T13:14:52.420 に答える