Litedb: Using PredicateBuilder return NotSupportedException [BUG]

Created on 9 Sep 2020  路  9Comments  路  Source: mbdavid/LiteDB

Version
5.0.9
Code to Reproduce
For simplicity:

  • I use a very simple query to describe the issue
  • I'm using LINQPad,
void Main()
{
    var cs = new ConnectionString
    {
        Filename = @"c:\mydb.db",
        Password = @"MyP@55w0rd"
    };
    using (var db = new LiteDatabase(cs))
    {
        var col = db.GetCollection<Product>("Prods");
        col.Insert(new Product{ Name="AAA"});
        col.Insert(new Product{ Name="AEE"});

        var predicate = PredicateBuilder.False<Product>();

        predicate = predicate.Or(p => p.Name.Contains("A"));
        col.Find(predicate).Count().Dump(); //<== NotSupportedException 
    }
}
public class Product
{
    public int Id{get;set;}
    public string Name{get;set;}
}

Expected behavior
The Count method should return the number of documents

Stacktrace

at LiteDB.LinqExpressionVisitor.Resolve(Boolean predicate)聽聽 
at LiteDB.BsonMapper.GetExpression[T,K](Expression`1 predicate)聽聽 
at LiteDB.LiteCollection`1.Find(Expression`1 predicate, Int32 skip, Int32 limit)聽聽 
at UserQuery.Main(), line 20

Exception Message

Invalid BsonExpression when converted from Linq expression: f => (False OrElse Invoke(p => p.Name.Contains("A"), f)) - `(((@p0) = true) OR @.Name LIKE ('%' + @p1 + '%')$)`

LiteException

Unexpected token `$` in position 49. 

Any help would be greatly appreciated.

bug

Most helpful comment

@toumir This issue has been fixed in the master and its fix will be present in the next incremental release. In the meantime, I suggest you use the ILiteQueryable<T> interface from col.Query(), for which I gave an example in my previous comment.

All 9 comments

@toumir Yes, it is a bug. The resulting BsonExpression is slightly wrong, it is being created with an additional $ at the end, which makes it invalid. I'm going to investigate it, but you could simply use col.Find(p => p.Name.Contains("A")), dropping PredicateBuilder altogether.

Thank you @lbnascimento, like I said, the real query is very complex and I must use the PredicateBuilder to build it dynamically,
in LiteDB v4 I was able to use List<Query> and build my query, but not in v5, I get this Error :
cannot convert from 'LiteDB.BsonExpression' to 'LiteDB.Query'

this code not work any more in v5:

var queries = new List<Query>();
if(condition)
{
    queries.Add(Query.EQ(nameof(Tiers.IsSpecial), isSpecial));
}

if(condition2)
{
    queries.Add(Query.Or(Query.EQ(nameof(Tiers.Type), typeTiers), Query.EQ(nameof(Tiers.Type), 3)));
}
...
db.GetCollection<Tiers>(nameof(Tiers)).Count(queries.ToArray()); //use case

have you a best solution?
Thanks in advance

@toumir You could do something like this:

```C#
var col = db.GetCollection();

...

var query = col.Query();

if(condition)
{
query.Where(x => x.Tiers.IsSpecial == isSpecial);
}

if(condition2)
{
query.Where(x => x.Tiers.Type == typeTiers || x.Tiers.Type == 3);
}

var count = query.Count();
```

FYI : For completeness, build and pass predicate to Collection / Query method, even without using PredicateBuilder lead to the same error :

Expression<Func<Product,bool>> predicate = p=>true;
predicate = predicate.And(p => p.Name.Contains("F"));

col.Count(predicate); //Exception

var qry = col.Query();
qry.Where(predicate).Count();//Exception

@toumir This issue has been fixed in the master and its fix will be present in the next incremental release. In the meantime, I suggest you use the ILiteQueryable<T> interface from col.Query(), for which I gave an example in my previous comment.

Still can't execute Find/Count with dynamically built predicates,
LiteDB version master branch with the fixed bug above,

Let say I have two methods that return a predicates:

  • The first returns var predicate1 = t=>true;
  • and the second returns the same thing var predicate2 = t=>true

After combining the two results : var result = predicate1.And(predicate2); and call the find method
col.Find(result);
I get this error:
Expression '@p1' are not supported as predicate expression.

Can someone help

@lbnascimento Any chances getting a snapshot version or a 5.0.10 including the fix? Unfortunately, I have the same issue.

@lbnascimento waiting for the next release, what I'm doing, I cloned the repository, compiled it at my level and referenced the dll

I'm also looking for a fix for this. I have so very much code using PredicateBuilder that I really don't want to rewrite, plus I am unsure how I can substitute col.Query() for every single instance (queries with dynamic and complex and's and or's, using predicates with DeleteMany(), etc.).

@lbnascimento Am I missing some documentation page on how to use Query()? I can't find anything.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

manny42 picture manny42  路  3Comments

kuiperzone picture kuiperzone  路  4Comments

onurhkb picture onurhkb  路  4Comments

axelgenus picture axelgenus  路  3Comments

ghiboz picture ghiboz  路  4Comments