0

linq to sql データ コンテキストをカプセル化するオブジェクトがあります。

IQuerable<T> FromStore<T>linq to sql を介して適切なテーブルからエンティティを取得できるメソッドがあります。

また、データ コンテキストで関数を呼び出すためのコールスルー メソッドもあります。

私が今抱えている問題は、sql への変換がないため、where 句内でこれらのパススルー メソッドを使用できないことです。原因はわかりましたが、どうすれば回避できますか?


コード例:

私のリポジトリクラスでは:

public class AquaReportsRepository : LinqToSqlRepository<int>, IAquaReportsRepository
{
    public bool IsPhysicalItem(string itemNumber)
    {
        return _UnderlyingDataContext.Aqua_IsPhysicalItem(itemNumber) ?? true;
    }
}

そこからデータにアクセスしようとしています:

from part in Repository.FromStore<Parts>()
where !(Repository.IsPhysicalItem(part.Item)) // eek, not translation to sql
select part.ItemNumber;

過去に、別のプロパティから計算されたデータオブジェクトの単純なプロパティが必要だった場合、QueryMapを使用してプロパティを同等の式に変換しましたが、必要があるため、ここでそれを行うことはできないと思いますdatacontext メソッドにアクセスします。

4

1 に答える 1

0

TL;DR : ポイント 1 の例を読んでください。QueryMap のコードを使用して、以下の太字の部分を変更してください。


そうですね、 QueryMapに若干の変更を加えることで、この問題を回避できました。

私が仕事をするために必要な2つのことがありました:

  1. データ コンテキストを使用するメソッドを呼び出すように querymap に指示する方法がわかりましたか?

  2. インターフェイスを介してアクセスされたときに、クラスで定義された属性を取得するためにクエリマップを取得する方法を理解してください。

最初の部分はかなり単純でした:

private static readonly ExpressionMethod<Func<AquaReportsRepository, string, bool>> _IsPhysicalItem =
    ExpressionMethod.Create((AquaReportsRepository ardc, string i) => ardc._AquaReportsDC.Aqua_IsPhysicalItem(i) ?? true);

[MapToExpression("_IsPhysicalItem")]
public bool IsPhysicalItem(string itemNumber)
{
    return _IsPhysicalItem.Invoke(this, itemNumber);
}

ここで重要なのはAquaReportsRepository、通常の他の引数に加えて、オブジェクト自体を最初の引数 (この場合) として受け取る関数を使用することです。

ただし、2 番目の部分では、 にいくつかの (かなりマイナーな) 変更が必要でしたMappedQueryVisitor.cs。どちらの場合も、if ステートメントは 1 つだけです (内部にステートメントがあります!)。

既存のGetLambdaメソッドを次のように置き換えます。

private LambdaExpression GetLambda(Expression receiver, MemberInfo member) {

    LambdaExpression exp;
    if(!_mappings.TryGetValue(member, out exp)) {
        exp = _mappingLookup(member);
        if(null == exp) {
            var attr = (MapToExpressionAttribute) member.GetCustomAttributes(typeof(MapToExpressionAttribute), true).FirstOrDefault();

            // Added by me to deal with interfaces
            if (null == attr)
            {
                if (null != receiver)
                {
                    // member could be an interface's member, so check the receiver.object type
                    if (receiver.NodeType == ExpressionType.Constant)
                    {
                        var receiverType = ((ConstantExpression)receiver).Value.GetType();

                        var receiverMemberInfo = receiverType.GetMembers().Where(mi => mi.Name == member.Name).SingleOrDefault();

                        if (null != receiverMemberInfo)
                        {
                            attr = (MapToExpressionAttribute)receiverMemberInfo.GetCustomAttributes(typeof(MapToExpressionAttribute), true).FirstOrDefault();
                            member = receiverMemberInfo;
                        }
                    }
                }
            }


            if(null != attr) {
                exp = GetLambdaFromAttribute(receiver, member.DeclaringType, attr);
            }
        }
        _mappings.Add(member, exp);
    }
    return exp;
}

この変更はmember MethodInfo、インターフェイス メソッドを表すオブジェクトがある場合、それを認識し、MethodInfo使用している具体的な型 (定数式で定義) の実際の値を取得しようとすることを意味します。

インターフェイスの をMapToExpressionAttribute指定すると、実装クラスの属性が正しく取得されるようになりました。MemberInfo

ただし、次の問題は ですVisitMethodCall。属性から呼び出す置換式を取得すると、引数式がインターフェイス タイプであるため、呼び出しているメソッドによって実装クラスが必要になるため、失敗します。

この最後のコード変更はそれを修正します。

CollectArgumentsメソッドを次のように変更します。

private static IEnumerable<Expression> CollectArguments(MethodCallExpression m) {
    IEnumerable<Expression> args = m.Arguments;
    if (!m.Method.IsStatic)
    {
        var objectExpression = m.Object;

        // Added by me, to deal with interfaces
        if (objectExpression.NodeType == ExpressionType.Constant)
        {
            var objectConstExpression = ((ConstantExpression)objectExpression);

            if (objectConstExpression.Type.IsInterface)
            {
                objectExpression = Expression.Constant(objectConstExpression.Value);
            }
        }

        args = Enumerable.Repeat(objectExpression, 1).Concat(args);
    }
    return args;
}
于 2013-10-02T13:54:00.857 に答える