2017-02-14 17 views
5

は、私は次の問題している:私は IQUeryable <T>で使用される述語(式<Func<T,bool>>)を取得して別のラムダ関数に適用できますか?

  • IQueryable<T>をMongoDBのを照会するために使用される
  • このIQueryable<T>をLinqToQueryStringからIQueryable<T>

    • を取得するかを決定するためにページングされたデータセットだけでなく、項目の合計数を返すために使用されますページなど
    • MongoDBは、IQueryable<T>.Where().Count()のCountにグループbyを追加します。これにより、カウント操作が非常に遅く実行されます。

    考えられる解決策:

    • IQueryable<T>からExpression<Func<T,bool>>を取得し、mongoCollection<T>.Count(filter)に適用します。これは問題をバイパスします。

    私はIQueryable<T> .Expressionから「どこで」を取得し、DynamicExpression.ParseLambda()で使用できる形式にExpressionTypeを操作しようとしています。ほとんどの場合、これはコードをDateTime式でテストするまでうまくいきました。

    ローカルのMongoDBインストールを使用してデータを入力し、ExpressionVisitorから作成された新しいExpressionを使用してCountを実行するLINQPadスクリプトを添付しました。

    新しいMongoDB FilterDefinitionBuilder<T>.Where(originalWhereExpression)の元の式から "Where"を簡単に再利用することができたらと思っています。

    スクリプトの依存関係は、以下のとおりです。 References (F4)

    コード:

    <Query Kind="Program"> 
        <Reference>&lt;RuntimeDirectory&gt;\System.Linq.dll</Reference> 
        <Reference>&lt;RuntimeDirectory&gt;\System.Linq.Expressions.dll</Reference> 
        <Reference>&lt;RuntimeDirectory&gt;\System.Linq.Queryable.dll</Reference> 
        <NuGetReference>Faker</NuGetReference> 
        <NuGetReference>LINQKit.Core</NuGetReference> 
        <NuGetReference>mongocsharpdriver</NuGetReference> 
        <NuGetReference>MongoDB.Driver</NuGetReference> 
        <NuGetReference>NBuilder</NuGetReference> 
        <NuGetReference>Newtonsoft.Json</NuGetReference> 
        <NuGetReference>System.Linq.Dynamic</NuGetReference> 
        <Namespace>FizzWare.NBuilder</Namespace> 
        <Namespace>LinqKit</Namespace> 
        <Namespace>MongoDB.Bson</Namespace> 
        <Namespace>MongoDB.Bson.Serialization.Attributes</Namespace> 
        <Namespace>MongoDB.Driver</Namespace> 
        <Namespace>MongoDB.Driver.Builders</Namespace> 
        <Namespace>MongoDB.Driver.Linq</Namespace> 
        <Namespace>myAlias = System.Linq.Dynamic</Namespace> 
        <Namespace>Newtonsoft.Json</Namespace> 
        <Namespace>System.Linq</Namespace> 
        <Namespace>System.Linq.Expressions</Namespace> 
        <Namespace>System.Threading.Tasks</Namespace> 
        <Namespace>System.Threading.Tasks.Dataflow</Namespace> 
    </Query> 
    
    private string _mongoDBConnectionString = "mongodb://localhost"; 
    private string _mongoDBDatabase = "LinqToQ"; 
    private string _mongoDBCollection = "People"; 
    
    private IMongoClient _mongoClient; 
    private IMongoDatabase _mongoDb; 
    
    private int _demoCount = 100000; 
    private bool _doPrep = true; 
    
    void Main() 
    { 
        _connectToMongoDB(); 
    
        if (_doPrep) 
         _prepMongo(); 
    
        var mongoDataQuery = _queryDemoData().Result; 
        mongoDataQuery.Expression.ToString().Dump("Original Expression"); 
    
        var whereFinder = new WhereFinder(); 
        whereFinder.SetWhere(mongoDataQuery.Expression); 
    
        var tempColl = _getPeopleCollection(); 
    
        if (!string.IsNullOrEmpty(whereFinder.WhereClause)) 
        { 
         var filter = new FilterDefinitionBuilder<Person>(); 
         tempColl.Count(filter.Where(_createWherePredicate<Person>(whereFinder.GetLambdaParts<Person>()))).Dump("Dynamic where count"); 
        } 
        else 
         tempColl.Count(FilterDefinition<Person>.Empty).Dump("No filter count"); 
    
        "Done".Dump(); 
    } 
    
    // Define other methods and classes here 
    
    // 
    private void _replaceExpressionTypes(ref StringBuilder whereBuilder, Dictionary<ExpressionType,string> expressionTypes) 
    { 
        foreach (var expType in expressionTypes.Keys) 
        { 
         whereBuilder.Replace($" {expType} ", $" {expressionTypes[expType]} "); 
        } 
    
        var openBracketCount = whereBuilder.ToString().Count(s => s == char.Parse("(")); 
        var closeBracketCount = whereBuilder.ToString().Count(s=> s==char.Parse(")")); 
    
        //whereBuilder.Replace("new DateTime(1974, 1, 1)","\"1974-01-01T00:00:00.00Z\""); 
        whereBuilder.Insert(0,"(",1); 
        whereBuilder.Append(")"); 
    
        $"OpenBrackets: {openBracketCount} vs CloseBrackets: {closeBracketCount}".Dump("Found Brackets"); 
    
        if(openBracketCount==closeBracketCount) 
         return; 
        if (openBracketCount > closeBracketCount) 
        { 
         var firstopenBracket = whereBuilder.ToString().IndexOf("("); 
         whereBuilder.Remove(firstopenBracket,1); 
        } 
        var lastCloseBracket = whereBuilder.ToString().LastIndexOf(")"); 
        if(lastCloseBracket>-1) 
         whereBuilder.Remove(lastCloseBracket,1); 
    } 
    private Dictionary<ExpressionType, string> _buildExpressionTypePairs() 
    { 
        var result = new Dictionary<ExpressionType, string>(); 
    
        result.Add(ExpressionType.Not, "!"); 
        result.Add(ExpressionType.Add, "+"); 
        result.Add(ExpressionType.AddChecked, "+"); 
        result.Add(ExpressionType.Subtract, "-"); 
        result.Add(ExpressionType.SubtractChecked, "-"); 
        result.Add(ExpressionType.Multiply, "*"); 
        result.Add(ExpressionType.MultiplyChecked, "*"); 
        result.Add(ExpressionType.Divide, "/"); 
        result.Add(ExpressionType.Modulo, "%"); 
        result.Add(ExpressionType.And, "&"); 
        result.Add(ExpressionType.AndAlso, "&&"); 
        result.Add(ExpressionType.Or, "|"); 
        result.Add(ExpressionType.OrElse, "||"); 
        result.Add(ExpressionType.LessThan, "<"); 
        result.Add(ExpressionType.LessThanOrEqual, "<="); 
        result.Add(ExpressionType.GreaterThan, ">"); 
        result.Add(ExpressionType.GreaterThanOrEqual, ">="); 
        result.Add(ExpressionType.Equal, "=="); 
        result.Add(ExpressionType.NotEqual, "!="); 
    
        return result; 
    } 
    private Expression<Func<Person, bool>> _createWherePredicate<T>(LamdaParts<T> lamdaParts) 
    { 
        var whereBuilder = new StringBuilder(lamdaParts.ExpressionString); 
        _replaceExpressionTypes(ref whereBuilder, _buildExpressionTypePairs()); 
    
        whereBuilder.ToString().Dump("Manipulated where cluase"); 
    
        var parameter = Expression.Parameter(lamdaParts.ParamterType, lamdaParts.ExpressionParameter); 
        //lamdaParts.ParamterType.Dump("Parameter"); 
        //var parameter = Expression.Parameter(typeof(Person), "p"); 
        var expression = myAlias.DynamicExpression.ParseLambda(new[] { parameter }, null, whereBuilder.ToString()); 
    
        //return Expression.Lambda<Func<Person, bool>>(whereExpression, parameter); 
        return Expression.Lambda<Func<Person, bool>>(expression.Body, expression.Parameters); 
    } 
    private async Task<IMongoQueryable<Person>> _queryDemoData() 
    { 
        var people = _getPeopleCollection(); 
    
        return people.AsQueryable().Where(p => p.DateOfBirth <= new DateTime(1974, 1, 1)); 
        //return people.AsQueryable().Where(p => p.LastName == "Anderson" && p.FirstName.Contains("f") && p.DateOfBirth >= new DateTime(1968, 1, 1) && p.DateOfBirth < new DateTime(1974, 1, 1)); 
        //return people.AsQueryable().Where(p => p.LastName == "Anderson" && p.FirstName.Contains("f") && (p.DateOfBirth>=new DateTime(1968,1,1) && p.DateOfBirth<new DateTime(1974,1,1))); 
        //return people.AsQueryable().Where(p => p.LastName == "Anderson" && p.FirstName.Contains("f")); 
        //return people.AsQueryable().Where(p => p.FirstName.Contains("f")); 
        //return people.AsQueryable().Where(p => p.LastName == "Anderson"); 
    
    } 
    private void _prepMongo() 
    { 
        _mongoDb.DropCollection(_mongoDBCollection, CancellationToken.None); 
    
        var testData = _getDemoList(_demoCount); 
        var people = _getPeopleCollection(); 
    
        people.Indexes.CreateOne(Builders<Person>.IndexKeys.Ascending(_ => _.LastName)); 
        people.Indexes.CreateOne(Builders<Person>.IndexKeys.Ascending(_ => _.Email)); 
    
        testData.ForEachOverTpl((person) => 
        { 
         people.InsertOneAsync(person).Wait(); 
        }); 
    
        $"Inserted {testData.Count} demo records".Dump(); 
    } 
    private IList<Person> _getDemoList(int demoCount) 
    { 
        var result = Builder<Person>.CreateListOfSize(demoCount) 
         .All() 
         .With(p => p.FirstName = Faker.NameFaker.FirstName()) 
         .With(p => p.LastName = Faker.NameFaker.LastName()) 
         .With(p => p.Email = Faker.InternetFaker.Email()) 
         .With(p => p.DateOfBirth = Faker.DateTimeFaker.BirthDay(21,50)) 
         .Build(); 
    
        return result; 
    } 
    private IMongoCollection<Person> _getPeopleCollection() 
    { 
        return _mongoDb.GetCollection<Person>(_mongoDBCollection); 
    } 
    private void _connectToMongoDB() 
    { 
        _mongoClient = new MongoClient(_mongoDBConnectionString); 
        _mongoDb = _mongoClient.GetDatabase(_mongoDBDatabase); 
    } 
    
    public class Person 
    { 
        [BsonId] 
        public string Id { get; set; } 
        public string FirstName { get; set; } 
        public string LastName { get; set; } 
        public string Email { get; set; } 
        public DateTime DateOfBirth { get; set; } 
    
    } 
    public class WhereFinder : MongoDB.Driver.Linq.ExpressionVisitor 
    { 
        //private IList<MethodCallExpression> whereExpressions = new List<MethodCallExpression>(); 
        private bool _foundWhere = false; 
        private bool _setWhere = false; 
    
        public string WhereClause { get; set; } 
        public string Parameter { get; set; } 
    
    
        public LamdaParts<T> GetLambdaParts<T>() 
        { 
         return new LamdaParts<T> { 
          ExpressionParameter=Parameter, 
          ExpressionString = WhereClause 
         }; 
        } 
        public void SetWhere(Expression expression) 
        { 
         Visit(expression); 
         //return whereExpressions; 
        } 
    
        protected override Expression VisitBinary(BinaryExpression node) 
        { 
         //$"{node.Left} {_convertNodeType(node.NodeType)} {node.Right}".Dump(); 
         if (_foundWhere && !_setWhere) 
         { 
          //node.ToString().Dump("VisitBinary"); 
          $"{node.Left} {_convertNodeType(node.NodeType)} {node.Right}".Dump("Setting Where Clause"); 
          WhereClause= $"{node.Left} {_convertNodeType(node.NodeType)} {node.Right}"; 
          //WhereClause.Dump("WhereClause"); 
          _setWhere=true; 
         } 
         return base.VisitBinary(node); 
        } 
        private string _convertNodeType(ExpressionType nodeType) 
        { 
         switch (nodeType) 
         { 
          case ExpressionType.Not: 
           return "!"; 
          case ExpressionType.Add: 
          case ExpressionType.AddChecked: 
           return "+"; 
          case ExpressionType.Subtract: 
          case ExpressionType.SubtractChecked: 
           return "-"; 
          case ExpressionType.Multiply: 
          case ExpressionType.MultiplyChecked: 
           return "*"; 
          case ExpressionType.Divide: 
           return "/"; 
          case ExpressionType.Modulo: 
           return "%"; 
          case ExpressionType.And: 
           return "&"; 
          case ExpressionType.AndAlso: 
           return "&&"; 
          case ExpressionType.Or: 
           return "|"; 
          case ExpressionType.OrElse: 
           return "||"; 
          case ExpressionType.LessThan: 
           return "<"; 
          case ExpressionType.LessThanOrEqual: 
           return "<="; 
          case ExpressionType.GreaterThan: 
           return ">"; 
          case ExpressionType.GreaterThanOrEqual: 
           return ">="; 
          case ExpressionType.Equal: 
           return "=="; 
          case ExpressionType.NotEqual: 
           return "!="; 
          default: 
           throw new Exception(string.Format("Unhandled expression type: '{0}'", nodeType)); 
         } 
        } 
    
        protected override Expression VisitParameter(ParameterExpression node) 
        { 
         if (_foundWhere) 
         { 
          //node.ToString().Dump("VisitParameter"); 
          Parameter=node.ToString(); 
         } 
         return base.VisitParameter(node); 
        } 
    
        protected override Expression VisitMethodCall(MethodCallExpression expression) 
        { 
         if (expression.Method.Name == "Where") 
         { 
          //whereExpressions.Add(expression); 
          _foundWhere = true; 
         } 
    
         if (expression?.Arguments != null) 
         { 
          foreach (var arg in expression.Arguments) 
          { 
           Visit(arg); 
          } 
         } 
    
         return expression; 
        } 
    } 
    public class LamdaParts<T> 
    { 
        public Type ParamterType 
        { 
         get 
         { 
          return typeof(T); 
         } 
        } 
        public string ExpressionParameter { get; set; } 
        public string ExpressionString { get;set;} 
    } 
    public static class Extensions 
    { 
        public static void ForEachOverTpl<T>(this IEnumerable<T> enumerable, Action<T> call) 
        { 
         var cancellationTokenSource = new CancellationTokenSource(); 
         var actionBlock = new ActionBlock<T>(call, new ExecutionDataflowBlockOptions 
         { 
          TaskScheduler = TaskScheduler.Current, 
          MaxDegreeOfParallelism = Environment.ProcessorCount * 2, 
          CancellationToken = cancellationTokenSource.Token, 
         }); 
         foreach (T item in enumerable) 
         { 
          if (cancellationTokenSource.IsCancellationRequested) return; 
          actionBlock.Post(item); 
         } 
         actionBlock.Complete(); 
         actionBlock.Completion.Wait(cancellationTokenSource.Token); 
        } 
    } 
    

  • 答えて

    3

    ソリューションを使用すると、式ツリーと可能なルートレベル表現方法の名前を理解すれば非常に簡単です。 @ bolankiに助けてくれてありがとう。更新LINQPadスクリプトが添付され

    (テストには_doPrep = trueを設定):

    <Query Kind="Program"> 
        <Reference>&lt;RuntimeDirectory&gt;\System.Linq.dll</Reference> 
        <Reference>&lt;RuntimeDirectory&gt;\System.Linq.Expressions.dll</Reference> 
        <Reference>&lt;RuntimeDirectory&gt;\System.Linq.Queryable.dll</Reference> 
        <NuGetReference>Faker</NuGetReference> 
        <NuGetReference>mongocsharpdriver</NuGetReference> 
        <NuGetReference>MongoDB.Driver</NuGetReference> 
        <NuGetReference>NBuilder</NuGetReference> 
        <NuGetReference>Newtonsoft.Json</NuGetReference> 
        <NuGetReference>System.Linq.Dynamic</NuGetReference> 
        <Namespace>FizzWare.NBuilder</Namespace> 
        <Namespace>MongoDB.Bson</Namespace> 
        <Namespace>MongoDB.Bson.Serialization.Attributes</Namespace> 
        <Namespace>MongoDB.Driver</Namespace> 
        <Namespace>MongoDB.Driver.Builders</Namespace> 
        <Namespace>MongoDB.Driver.Linq</Namespace> 
        <Namespace>myAlias = System.Linq.Dynamic</Namespace> 
        <Namespace>Newtonsoft.Json</Namespace> 
        <Namespace>System.Linq</Namespace> 
        <Namespace>System.Linq.Expressions</Namespace> 
        <Namespace>System.Threading.Tasks</Namespace> 
        <Namespace>System.Threading.Tasks.Dataflow</Namespace> 
    </Query> 
    
    private string _mongoDBConnectionString = "mongodb://localhost"; 
    private string _mongoDBDatabase = "LinqToQ"; 
    private string _mongoDBCollection = "People"; 
    
    private IMongoClient _mongoClient; 
    private IMongoDatabase _mongoDb; 
    
    private int _demoCount = 2000000; 
    private bool _doPrep = false; 
    
    void Main() 
    { 
        _connectToMongoDB(); 
    
        // Should demo data be generated 
        if (_doPrep) 
         _prepMongo(); 
    
        // Get the queryable to test with 
        var mongoDataQuery = _getIQueryable(); 
        // Print the original expression  
        //mongoDataQuery.Expression.ToString().Dump("Original Expression"); 
    
        // Evaluate the expression and try find the where expression 
        var whereFinder = new WhereFinder<Person>(mongoDataQuery.Expression); 
    
        // Get the MongoCollection to be Filtered and Count 
        var tempColl = _getPeopleCollection(); 
    
        if (whereFinder.FoundWhere) 
        { 
         //whereFinder.TheWhereExpression.ToString().Dump("Calculated where expression"); 
         var filter = new FilterDefinitionBuilder<Person>(); 
         var stopwatch = new Stopwatch(); 
         stopwatch.Start(); 
         tempColl.Count(filter.Where(whereFinder.TheWhereExpression)).Dump("Dynamic where count"); 
         var afterCalculatedWhere = stopwatch.Elapsed; 
         mongoDataQuery.Count().Dump("IQueryable<T> where count"); 
         var afterIQuerableWhere = stopwatch.Elapsed; 
         stopwatch.Stop(); 
    
         $"Calculated where:{afterCalculatedWhere:c}\nIQueryable where:{afterIQuerableWhere:c}".Dump("Where Durations"); 
        } 
        else 
         tempColl.Count(FilterDefinition<Person>.Empty).Dump("No filter count"); 
    
        "Done".Dump(); 
    } 
    
    /////////////////////////////////////////////////////// 
    // END SOLUTION 
    /////////////////////////////////////////////////////// 
    private IMongoQueryable<Person> _getIQueryable() 
    { 
        var people = _getPeopleCollection(); 
    
        //return people.AsQueryable().Where(p => p.DateOfBirth <= new DateTime(1974, 1, 1)); 
        return people.AsQueryable().Where(p => p.LastName == "Anderson" && p.FirstName.Contains("f") && p.DateOfBirth >= new DateTime(1968, 1, 1) && p.DateOfBirth < new DateTime(1974, 1, 1)); 
        //return people.AsQueryable().Where(p => p.LastName == "Anderson" && p.FirstName.Contains("f") && (p.DateOfBirth>=new DateTime(1968,1,1) && p.DateOfBirth<new DateTime(1974,1,1))); 
        //return people.AsQueryable().Where(p => p.LastName == "Anderson" && p.FirstName.Contains("f")); 
        //return people.AsQueryable().Where(p => p.FirstName.Contains("f")); 
        //return people.AsQueryable().Where(p => p.LastName == "Anderson"); 
    
    } 
    public class Person 
    { 
        [BsonId] 
        public string Id { get; set; } 
        public string FirstName { get; set; } 
        public string LastName { get; set; } 
        public string Email { get; set; } 
        public DateTime DateOfBirth { get; set; } 
    
    } 
    public class WhereFinder<T> : MongoDB.Driver.Linq.ExpressionVisitor 
    { 
        private bool _processingWhere = false; 
        private bool _processingLambda = false; 
        public ParameterExpression _parameterExpression { get; set; } 
    
        public WhereFinder(Expression expression) 
        { 
         Visit(expression); 
        } 
    
        public Expression<Func<T, bool>> TheWhereExpression { get; set; } 
        public bool FoundWhere 
        { 
         get { return TheWhereExpression != null; } 
        } 
    
        protected override Expression VisitBinary(BinaryExpression node) 
        { 
         var result = base.VisitBinary(node); 
         if(_processingWhere) 
          TheWhereExpression = (Expression<Func<T, bool>>)Expression.Lambda(node, _parameterExpression); 
         return result; 
        } 
        protected override Expression VisitParameter(ParameterExpression node) 
        { 
         if (_processingWhere || _processingLambda || _parameterExpression==null) 
          _parameterExpression = node; 
         return base.VisitParameter(node); 
        } 
        protected override Expression VisitMethodCall(MethodCallExpression expression) 
        { 
         string methodName = expression.Method.Name; 
         if (TheWhereExpression==null && (methodName == "Where" || methodName == "Contains")) 
         { 
          _processingWhere = true; 
          if (expression?.Arguments != null) 
           foreach (var arg in expression.Arguments) 
            Visit(arg); 
          _processingWhere = false; 
         } 
    
         return expression; 
        } 
        protected override Expression VisitLambda(LambdaExpression exp) 
        { 
         if (_parameterExpression == null) 
          _parameterExpression = exp.Parameters?.FirstOrDefault(); 
    
         TheWhereExpression = (Expression<Func<T, bool>>)Expression.Lambda(exp.Body, _parameterExpression); 
         return exp; 
        } 
    
    } 
    /////////////////////////////////////////////////////// 
    // END SOLUTION 
    /////////////////////////////////////////////////////// 
    
    
    
    /////////////////////////////////////////////////////// 
    // BEGIN DEMO DATA 
    /////////////////////////////////////////////////////// 
    private void _prepMongo() 
    { 
        _mongoDb.DropCollection(_mongoDBCollection, CancellationToken.None); 
    
        var testData = _getDemoList(_demoCount); 
        var people = _getPeopleCollection(); 
    
        people.Indexes.CreateOne(Builders<Person>.IndexKeys.Ascending(_ => _.FirstName)); 
        people.Indexes.CreateOne(Builders<Person>.IndexKeys.Ascending(_ => _.LastName)); 
        people.Indexes.CreateOne(Builders<Person>.IndexKeys.Ascending(_ => _.Email)); 
        people.Indexes.CreateOne(Builders<Person>.IndexKeys.Ascending(_ => _.DateOfBirth)); 
    
        $"Inserting ...{testData.Count}... demo records".Dump(); 
    
        Extensions.ForEachOverTpl<Person>(testData, (person) => 
        { 
         people.InsertOneAsync(person).Wait(); 
        }); 
    
        $"Inserted {testData.Count} demo records".Dump(); 
    } 
    private IList<Person> _getDemoList(int demoCount) 
    { 
        var result = Builder<Person>.CreateListOfSize(demoCount) 
         .All() 
         .With(p => p.FirstName = Faker.NameFaker.FirstName()) 
         .With(p => p.LastName = Faker.NameFaker.LastName()) 
         .With(p => p.Email = Faker.InternetFaker.Email()) 
         .With(p => p.DateOfBirth = Faker.DateTimeFaker.BirthDay(21, 50)) 
         .Build(); 
    
        return result; 
    } 
    private IMongoCollection<Person> _getPeopleCollection() 
    { 
        return _mongoDb.GetCollection<Person>(_mongoDBCollection); 
    } 
    private void _connectToMongoDB() 
    { 
        _mongoClient = new MongoClient(_mongoDBConnectionString); 
        _mongoDb = _mongoClient.GetDatabase(_mongoDBDatabase); 
    } 
    /////////////////////////////////////////////////////// 
    // END DEMO DATA 
    /////////////////////////////////////////////////////// 
    public static class Extensions 
    { 
        public static void ForEachOverTpl<T>(this IEnumerable<T> enumerable, Action<T> call) 
        { 
         var cancellationTokenSource = new CancellationTokenSource(); 
         var actionBlock = new ActionBlock<T>(call, new ExecutionDataflowBlockOptions 
         { 
          TaskScheduler = TaskScheduler.Current, 
          MaxDegreeOfParallelism = Environment.ProcessorCount * 2, 
          CancellationToken = cancellationTokenSource.Token, 
         }); 
         foreach (T item in enumerable) 
         { 
          if (cancellationTokenSource.IsCancellationRequested) return; 
          actionBlock.Post(item); 
         } 
         actionBlock.Complete(); 
         actionBlock.Completion.Wait(cancellationTokenSource.Token); 
        } 
    } 
    

    アップデート: -

    など、テイクを含む式のためのOrderByを修正
    public class WhereFinder<T> : MongoDB.Driver.Linq.ExpressionVisitor 
        { 
         private bool _processingWhere = false; 
         private bool _processingLambda = false; 
         public ParameterExpression _parameterExpression { get; set; } 
    
         public WhereFinder(Expression expression) 
         { 
         Visit(expression); 
         } 
    
         public Expression<Func<T, bool>> TheWhereExpression { get; set; } 
         public bool FoundWhere 
         { 
         get { return TheWhereExpression != null; } 
         } 
    
         protected override Expression Visit(Expression exp) 
         { 
         return base.Visit(exp); 
         } 
         protected override Expression VisitBinary(BinaryExpression node) 
         { 
         var result = base.VisitBinary(node); 
         if (_processingWhere) 
         { 
          TheWhereExpression = (Expression<Func<T, bool>>) Expression.Lambda(node, _parameterExpression); 
         } 
         return result; 
         } 
         protected override Expression VisitParameter(ParameterExpression node) 
         { 
         if (_processingWhere || _processingLambda || _parameterExpression == null) 
          _parameterExpression = node; 
         return base.VisitParameter(node); 
         } 
         protected override Expression VisitMethodCall(MethodCallExpression expression) 
         { 
         string methodName = expression.Method.Name; 
    
         if (methodName == "Where") 
          _processingWhere = true; 
         if (expression?.Arguments != null) 
          foreach (var arg in expression.Arguments) 
          Visit(arg); 
         _processingWhere = false; 
    
         return expression; 
        } 
        protected override Expression VisitLambda(LambdaExpression exp) 
        { 
         if (_processingWhere) 
         { 
          if (_parameterExpression == null) 
           _parameterExpression = exp.Parameters?.FirstOrDefault(); 
    
          TheWhereExpression = (Expression<Func<T, bool>>)Expression.Lambda(exp.Body, _parameterExpression); 
         } 
         return exp; 
        } 
    
    } 
    
    関連する問題