So here is the basic of what i want to achieve:
string.Format(new CultureInfo("da-DK"), "{0:n}", myDouble)
(Formatting a number with a culture. Example input: 1, output: "1,00")
Context: I need to achieve this with an expression tree, my current code produces a search query, going through product prices, in which it should format doubles. Here is what i've got so far:
var query = context.Products;
var searchquery = "1,00" //example
var propertyName = "Price"; //example
var parameterExp = Expression.Parameter(typeof(ProductClass), "type");
var propertyExp = Expression.Property(parameterExp, propertyName);
MethodCallExpression propertyExpToStringToLower; //value initialized depending on type.
if (propertyExp.Type == typeof(double))
{
// Example value: 1, needed value: "1,00".
// Here I want to change the double to the correct format, ToString.
}
else
{
//ToString's and ToLower's other attributes (string, int, where no format is needed)
propertyExpToStringToLower = Expression.Call(Expression.Call(propertyExp, propertyExp.Type.GetMethod("ToString", System.Type.EmptyTypes)), typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
}
MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var seachValue = Expression.Constant(searchquery.ToLower(), typeof(string));
var containsMethodExp = Expression.Call(propertyExpToStringToLower, method, seachValue);
Expression<Func<ProductClass, bool>> predicate = Expression.Lambda<Func<ProductClass, bool>>
(containsMethodExp, parameterExp);
query = query.Where(predicate);
As a quick side note, I am not very experienced with expression trees but the code is working with a string attribute like ProductName, Just not with numbers. I image I can call ToString with a format? But I have not been able to find any examples.
Question: How do I format an expression value with a format/culture?
It's not worth trying to build expression tree for string.Format(new CultureInfo("da-DK"), "{0:n}", myDouble)
(or ToString(new CultureInfo("da-DK"))
) calls, because you are using this expression tree with Entity Framework, and it will not be able to translate such statement to SQL query.
Instead of trying to convert database values to desired culture - convert your input to the culture database expects:
var searchquery = "1,00"; //example
var expectedCulture = new CultureInfo("da-DK");
var targetCulture = new CultureInfo("en-US"); // for example
double searchValue;
if (double.TryParse(searchquery, NumberStyles.AllowDecimalPoint, targetCulture, out searchValue)) {
searchquery = searchValue.ToString(targetCulture);
}
If you will go this route - you might notice that there might actually be no need to convert number back to string, because since you now know it's a number - you can compare it with equals and not ToString().Contains(...)
like you are doing now. ToString().Contains(...)
will produce quite bad SQL query, which will be forced to evaluate every row in the table. If you will compare price directly (that is, like: c => c.Price == doubleValue
) - you will be able to use database index on that column (if any), and even without index I'd expect it to execute faster. But note that such comparision is not exactly the same as Contains(...)
. For example if user types "1.00" - contains will return prices like "111.00", "231.00" and so on, while equality comparision will return just exact matches. Whether it is desirable to use Contains
or not when searching for prices - only you can decide.
Side note: using double
when working with prices is a bad idea. Use decimal
instead.