0

特定のタイプの検索用に独自のリフレクション関数を構築しています。

問題は、ID のリスト内で ID のグループを検索し、検索/選択クエリをフィルタリングして、これらの特定のオブジェクトのみを取得することです。

これは、Linq-Entity フレームワークで "IN()" を使用するのと同じです。しかし、a.objid は使用できません。

return query.Where(a => ObjectsToFind.Contains(a.objid));

ただし、T テンプレートを使用しているため、「a.objid」がエラーを引き起こしています。

したがって、a は「MyTable a」ではなく「T a」であるため、「objid」プロパティと呼ぶことができます。

パラメータ式でこれを行う方法があることは知っています。しかし、私はそれを理解することはできません。

上記の行を次の行に置き換えようとしたのは次のとおりです。

public static IQueryable<T> WhereFunctionContains<T>(this IQueryable<T> query, string contains)
{    
    var ObjectsToFind = new List<int>(); // I want to search IN() this function that gets filled in here.
    ObjectsToFind = FillObjectsToFind(); // just the object id integers I want to filter
    var parameter = Expression.Parameter(typeof(T), "type");
    var propertyExpression = Expression.Property(parameter, "objid"); // I look for this
    MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(int) }); // int type
    var vars = Expression.Variable(List<int>,); // I can't use "constant", but what do I use here?
    var containsExpression = Expression.Call(propertyExpression, method, vars);
    return query.Where(Expression.Lambda<Func<T, bool>>(containsExpression, parameter));
}

「T」を実際のテーブル エンティティに置き換えると、多くの問題が発生するため、T をそのまま使用することにしました。


else if (s.ST == "function")
{ // search func
    myTable a;
    DC2 = MyUtility.WhereFunctionContains(DC2, a => a.objid, s.S);
    // s.S is my search query string.
    // s.ST means I'm searching for functions (from another associated table)
    // I don't understand how a.objid gets called, I wanted to use Template/Reflections.
}

Zev の関数を呼び出す方法を次に示します。

public static IQueryable<T> WhereFunctionContains<T>(this IQueryable<T> query, Expression<Func<T, int>> converter, string contains)
{
    FunctionsClass fc = new FunctionsClass();
    var ObjectsToFind = new List<int>();
    ObjectsToFind = fc.SearchContainFunction(contains); // I grabbed my list of IDs to search
    return query.Where(t => ObjectsToFind.Contains(converter(t)));
}
4

1 に答える 1

2

私があなたを正しく理解していれば、さまざまなタイプのクエリがいくつかあります。

IQueryable<Person> personsQry = ...
IQueryable<Sale>   salesQry   = ...
IQueryable<Order>  ordersQry  = ...

List<int>と呼ばれるを生成するメソッドがありますFillObjectsToFind

public List<int> FillObjectsToFind()
{
    //code here
}

上記の各クエリを、返されるリストに id のみが含まれるように制限できるようにする必要があります。追加のボーナスとして、これは拡張メソッドである必要があるため、次のように呼び出すことができます。

var personsFiltered = personsQry.WhereFunctionContains(...);
var salesFiltered   = salesQry.WhereFunctionContains(...);
var ordersFiltered  = ordersQry.WhereFunctionContains(...);

問題は、各クエリが別々のタイプであり、それらすべてをカバーする 1 つのメソッドを作成することです。


ソリューションの最初の部分は、ジェネリック メソッドを定義することです。

public static IQueryable<T> WhereFunctionContains<T>(this IQueryable<T> query)
{
    //code here
}

しかし、まだ問題があります。私たちが知っている型Tは、実際の型ではなく、実際の型のプレースホルダーである型だけです。これらの型は、ASP.NET、WPF など、何でもかまいませんstring。各オブジェクトをのと比較する方法を知る方法はありません。 System.RandomSqlConnectionLabelTextBlockListints


最も簡単な解決策は、インターフェースを定義することです:

interface IHasObjID
{
    int ObjID {get;set;}
}

次に、各タイプはこのインターフェイスを実装する必要があります。

class Person : IHasObjID
{
    int objID;
    int ObjID
    {
        get {return objID;}
        set {objID = value;}
    }
}

//implement sales and orders similarly

それが完了したら、メソッドで許可される型に制約を定義できます。型が確実にObjIDプロパティを持つようになったので、それに対してクエリを実行できます。

public static IQueryable<T> WhereFunctionContains<T>(this IQueryable<T> query) where T : IHasObjID
{
    var intsToFind = FillObjectsToFind();
    return query.Where(t => intsToFind.Contains(t.ObjID));
}

これは、King Kingがこのコメント であなたに伝えていたことです。


この関数を呼び出すときに、型から整数を取得する方法も渡すことをお勧めします。

public static IQueryable<T> WhereFunctionContains<T>(this IQueryable<T> query, Expression<Func<T,int>> converter)
{    
    var intsToFind = FillObjectsToFind();
    return query.Where(t => intsToFind.Contains(converter(t)));
}

ただし、私はこのコードをテストしていません。また、Entity Framework と式を使用しているため、まだ問題があると思われます。式を式内で「呼び出す」ことはできません。 上記を提案したかったのですが、次のエラーでコンパイルされません- 'converter' is a 'variable' but used like a 'method' .

結局のところ、ソリューションは簡単で、次を使用しJoinます。

public static IQueryable<T> WhereFunctionContains<T>(this IQueryable<T> query, Expression<Func<T,int>> converter) 
{
    var ints = new List<int>() { 1, 2, 3, 4, 5 };
    return query.Join(ints,converter,i=>i,(t,i) => t);
}

次のように呼び出されます。

var filteredPersons = query.WhereFunctionContains(p => p.PersonID);


これが単一のタイプでのみ使用される場合MyTable:

public static IQueryable<MyTable> WhereFunctionContains(this IQueryable<MyTable> query)
{
    var ints = new List<int>() { 1, 2, 3, 4, 5 };
    return query.Join(ints, mt=>mt.objid, i=>i, (t,i) => t);
}


C# プログラミング ガイド からのいくつかのリンク(回答順):

また、 、、などのLINQ 演算子の概要については、こちらを参照してください。SelectWhereCountToList

于 2013-09-16T19:25:50.583 に答える