Dynamic Linq Predicate throws “Unsupported Filter” error with C# MongoDB Driver

a 夏天 提交于 2019-12-10 20:18:49

问题


I have been trying to pass in a dynamic list of Expressions to a MongoDB C# Driver query using Linq ... This method works for me with regular Linq queries against an ORM, for example, but results in an error when applied to a MongoDB query ... (FYI: I am also using LinqKit's 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);

The GetSessionMsgs() method is defined in a Data services class ...

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;
    }
}

Using the LinqKit PredicateBuilder I simply add the provided expressions into a single "AND" expression ... 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.

This technique typically works when I an going against my Telerik ORM Context Entity collections ... but when I run this against the Mongo Document Collection I get the following error ...

Unsupported filter: Invoke(e => (e.Region.ToLower() == "central"), {document})

There is certainly something going on beneath the covers that I am unclear on. In the C# Driver for MongoDB documentation I found the following NOTE ...

"When projecting scalars, the driver will wrap the scalar into a document with a generated field name because MongoDB requires that output from an aggregation pipeline be documents"

But honestly I am not sure what that neccessarily means or if it's related to this problem or not. The appearence of "{document}" in the error suggests that it might be relevant though.

Any additional thoughts or insight would be greatly appreciated though. Been stuck on this for the better part of 2 days now ...

I did find this post but so far am not sure how the accepted solution is much different than what I have done.


回答1:


.Where(predicate.Compile())

That will trigger using the Func<T, bool> method on the IQueryable<T> interface which the MongoDB driver will work just fine with.



来源:https://stackoverflow.com/questions/37056386/dynamic-linq-predicate-throws-unsupported-filter-error-with-c-sharp-mongodb-dr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!