Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataSourceLoadOptionsBase - provide option to skip StringToLower for specific fields #492

Open
drekoo opened this issue Sep 28, 2021 · 2 comments

Comments

@drekoo
Copy link

drekoo commented Sep 28, 2021

Hello,
is possible to implement new DataSourceLoadOptionsBase.SkipStringToLower option.
When I have some filter, I need case insensitive comparison just for some fields, but not for others (because of index search).

Best regards,
Darko

@AlekseyMartynov
Copy link
Contributor

Hello

You can use CustomFilterCompilers to intercept and modify filter expressions.

Example:

static void Main(string[] args) {
    CustomFilterCompilers.RegisterBinaryExpressionCompiler(SkipStringToLowerCompiler);

    using(var context = new NorthwindContext()) {
        var loadResult = DataSourceLoader.Load(context.Orders, new DataSourceLoadOptionsBase {
            RequireTotalCount = true,
            StringToLower = true, // default setting
            Filter = new object[] {
                new object[] { "ShipName", "=", "Wilman Kala" },
                new object[] { "ShipAddress", "contains", "Keskuskatu 45" }
            }
        });
    }

}

static Expression SkipStringToLowerCompiler(IBinaryExpressionInfo info) {
    if(info.DataItemExpression.Type == typeof(Orders) && (info.AccessorText == "ShipAddress" || info.AccessorText == "ShipName")) {
        var left = Expression.PropertyOrField(info.DataItemExpression, info.AccessorText);
        var right = Expression.Constant(Convert.ToString(info.Value));
        switch(info.Operation) {
            case "=":
                return Expression.Equal(left, right);
            case "contains":
                var method = typeof(String).GetMethod("Contains", new[] { typeof(String) });
                return Expression.Call(left, method, right);
        }
    }
    return null;
}

Resulting SQL:

SELECT COUNT(*)
FROM [Orders] AS [o]
WHERE ([o].[ShipName] = N'Wilman Kala') AND (CHARINDEX(N'Keskuskatu 45', [o].[ShipAddress]) > 0)

Compare with SQL w/o SkipStringToLowerCompiler:

SELECT COUNT(*)
FROM [Orders] AS [o]
WHERE (LOWER([o].[ShipName]) = N'wilman kala') AND (CHARINDEX(N'keskuskatu 45', LOWER([o].[ShipAddress])) > 0)

However, as you probably know, in SQL databases, case sensitivity is often controlled by table/column collation settings. If this is your case then you don't need to use StringToLower.

@drekoo
Copy link
Author

drekoo commented Sep 28, 2021

Ok, thank you very much for workaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants