5

Linq を使用して、式の動的リストを MongoDB C# ドライバー クエリに渡そうとしています...この方法は、たとえば、ORM に対する通常の Linq クエリで機能しますが、MongoDB クエリに適用するとエラーになります。 ... (参考: LinqKit の PredicateBuilder も使用しています)

//
// I create a List of Expressions which I can then add individual predicates to on an 
// "as-needed" basis.
    var filters = new List<Expression<Func<Session, Boolean>>>();

//
// If the Region DropDownList returns a value then add an expression to match it.
// (the WebFormsService is a home built service for extracting data from the various 
// WebForms Server Controls... in case you're wondering how it fits in)
    if (!String.IsNullOrEmpty(WebFormsService.GetControlValueAsString(this.ddlRegion)))
    {
        String region = WebFormsService.GetControlValueAsString(this.ddlRegion).ToLower();
        filters.Add(e => e.Region.ToLower() == region);
    }

//
// If the StartDate has been specified then add an expression to match it.
    if (this.StartDate.HasValue)
    {
        Int64 startTicks = this.StartDate.Value.Ticks;
        filters.Add(e => e.StartTimestampTicks >= startTicks);
    }

//
// If the EndDate has been specified then add an expression to match it.
    if (this.EndDate.HasValue)
    {
        Int64 endTicks = this.EndDate.Value.Ticks;
        filters.Add(e => e.StartTimestampTicks <= endTicks);
    }

//
// Pass the Expression list to the method that executes the query
    var data = SessionMsgsDbSvc.GetSessionMsgs(filters);

GetSessionMsgs() メソッドは、データ サービス クラスで定義されています ...

public class SessionMsgsDbSvc
{

    public static List<LocationOwnerSessions> GetSessionMsgs(List<Expression<Func<Session, Boolean>>> values)
    {
        //
        // Using the LinqKit PredicateBuilder I simply add the provided expressions 
        // into a single "AND" expression ...
            var predicate = PredicateBuilder.True<Session>();
            foreach (var value in values)
            {
                predicate = predicate.And(value);
            }

        //
        // ... and apply it as I would to any Linq query, in the Where clause.
        // Additionally, using the Select clause I project the results into a 
        // pre-defined data transfer object (DTO) and only the DISTINCT DTOs are returned
            var query = ApplCoreMsgDbCtx.Sessions.AsQueryable()
                .Where(predicate)
                .Select(e => new LocationOwnerSessions 
                    { 
                        AssetNumber = e.AssetNumber, 
                        Owner = e.LocationOwner, 
                        Region = e.Region 
                    })
                .Distinct();

            var data = query.ToList();

            return data;
    }
}

LinqKit PredicateBuilder を使用して、提供された式を 1 つの「AND」式に追加するだけです ...そして、Where() 句で、Linq クエリと同じように適用します。さらに、Select() 句を使用して、結果を定義済みのデータ転送オブジェクト (DTO) に射影し、DISTINCT DTO のみが返されます。

この手法は通常、Telerik ORM Context Entity コレクションに対して実行するときに機能します...しかし、Mongo ドキュメント コレクションに対してこれを実行すると、次のエラーが発生します...

サポートされていないフィルター: Invoke(e => (e.Region.ToLower() == "central"), {document})

確かに、私がはっきりしないカバーの下で何かが起こっています。C# Driver for MongoDB のドキュメントで、次の注を見つけました ...

「スカラーを射影するとき、MongoDB は集約パイプラインからの出力をドキュメントにする必要があるため、ドライバーは生成されたフィールド名を持つドキュメントにスカラーをラップします」

しかし、正直なところ、それが何を意味するのか、それがこの問題に関連しているかどうかはわかりません。ただし、エラーに「{document}」が表示されることは、関連性があることを示唆しています。

ただし、追加の考えや洞察は大歓迎です。これで2日間の大半が立ち往生しています...

私はこの投稿を見つけましたが、これまでのところ、受け入れられた解決策が私が行ったものとどのように大きく異なるかはわかりません.

4

1 に答える 1

7

私は4年後にこれを再訪するために戻ってきました。私の最初の仮定はうまくいきましたが、Mongoからすべてのレコードを引き戻し、メモリ内でそれらをフィルタリングし、問題を複雑にするために同期呼び出しを行っていたという間違った方法で機能したからですこれは常に悪い考えです。

LinqKit の expand 拡張メソッドで魔法が起こる

これにより、呼び出し式ツリーがフラット化されて、Mongo ドライバーが理解できるようになり、操作できるようになります。

.Where(predicate.Expand())
于 2016-07-19T00:34:09.543 に答える