简体   繁体   中英

C# expression works on the database, doesn't work in memory

I have a .NET Core 2.2 with Entity application which takes string input from an user, then converts it into expression and finally filters some data basing on it. This is the class building expression from a string (based on this article):

 public async Task<Expression<Func<T, bool>>> GetLinqExpression<T>(string rule)
 {
     var options = ScriptOptions.Default.AddReferences(typeof(T).Assembly);
     return await CSharpScript.EvaluateAsync<Expression<Func<T, bool>>>(rule, options);
 }

Expression works as expected when used on a db:

var linqExpression = await _linqService.GetLinqExpression<Item>(linqExpressionString);
var filteredItems = _dbContext.Items.Where(linqExpression).ToList();

But it doesn't when I'm trying to do the same in-memory using Compile() method.

var linqExpression = await _linqService.GetLinqExpression<Item>(linqExpressionString);
var items = _dbContext.Items.ToList();
var filteredItems = items.Where(linqExpression.Compile()).ToList();

In this case code runs successfully but filteredItems collection is empty. Why does it behave that way? How can I run this expression in-memory?

There may be a difference in how a filter expression is evaluated between "in memory" and "in database". Especially when you are filtering on string values!

In memory a string comparison ( value == "some value" or value.Contains("some value") ) is case sensitive.

In a database this depends on the collation that is set for that column/table/database. By default this is probably case INsensitive (in SqlServer the "CI" suffix on the collation means "Case Insensitive", while "AS" means "Accent Sensitive")

So the database might return more records than an in-memory datastore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM