format/culture 的表达式树 ToString
Expression tree ToString with format/culture
所以这是我想要实现的基本目标:
string.Format(new CultureInfo("da-DK"), "{0:n}", myDouble)
(使用文化格式化数字。示例输入:1,输出:“1,00”)
上下文:我需要使用表达式树来实现此目的,我当前的代码会生成一个搜索查询,遍历产品价格,其中格式应为双精度。
这是我到目前为止所得到的:
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);
顺便说一句,我对表达式树不是很有经验,但代码使用的是 ProductName 之类的字符串属性,而不是数字。我想象我可以用一种格式调用 ToString 吗?但是我没能找到任何例子。
问题: 如何用 format/culture 格式化表达式值?
不值得尝试为 string.Format(new CultureInfo("da-DK"), "{0:n}", myDouble)
(或 ToString(new CultureInfo("da-DK"))
)调用构建表达式树,因为您正在将此表达式树与 Entity Framework 一起使用,并且它将无法将此类语句翻译成 SQL 查询。
与其尝试将数据库值转换为所需的文化,不如将您的输入转换为数据库期望的文化:
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);
}
如果你走这条路 - 你可能会注意到实际上可能不需要将数字转换回字符串,因为你现在知道它是一个数字 - 你可以将它与 equals 而不是 ToString().Contains(...)
就像你现在做的那样。 ToString().Contains(...)
将产生非常糟糕的 SQL 查询,它将被迫评估 table 中的每一行。如果您将直接比较价格(即,如:c => c.Price == doubleValue
)- 您将能够在该列(如果有)上使用数据库索引,即使没有索引,我也希望它执行得更快。但是请注意,这样的比较并不完全等同于Contains(...)
。例如,如果用户输入“1.00”- 包含将 return 价格,如“111.00”、“231.00”等,而相等比较将 return 完全匹配。在搜索价格时是否需要使用 Contains
- 只有您可以决定。
旁注:在处理价格时使用 double
是个坏主意。请改用 decimal
。
所以这是我想要实现的基本目标:
string.Format(new CultureInfo("da-DK"), "{0:n}", myDouble)
(使用文化格式化数字。示例输入:1,输出:“1,00”)
上下文:我需要使用表达式树来实现此目的,我当前的代码会生成一个搜索查询,遍历产品价格,其中格式应为双精度。 这是我到目前为止所得到的:
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);
顺便说一句,我对表达式树不是很有经验,但代码使用的是 ProductName 之类的字符串属性,而不是数字。我想象我可以用一种格式调用 ToString 吗?但是我没能找到任何例子。
问题: 如何用 format/culture 格式化表达式值?
不值得尝试为 string.Format(new CultureInfo("da-DK"), "{0:n}", myDouble)
(或 ToString(new CultureInfo("da-DK"))
)调用构建表达式树,因为您正在将此表达式树与 Entity Framework 一起使用,并且它将无法将此类语句翻译成 SQL 查询。
与其尝试将数据库值转换为所需的文化,不如将您的输入转换为数据库期望的文化:
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);
}
如果你走这条路 - 你可能会注意到实际上可能不需要将数字转换回字符串,因为你现在知道它是一个数字 - 你可以将它与 equals 而不是 ToString().Contains(...)
就像你现在做的那样。 ToString().Contains(...)
将产生非常糟糕的 SQL 查询,它将被迫评估 table 中的每一行。如果您将直接比较价格(即,如:c => c.Price == doubleValue
)- 您将能够在该列(如果有)上使用数据库索引,即使没有索引,我也希望它执行得更快。但是请注意,这样的比较并不完全等同于Contains(...)
。例如,如果用户输入“1.00”- 包含将 return 价格,如“111.00”、“231.00”等,而相等比较将 return 完全匹配。在搜索价格时是否需要使用 Contains
- 只有您可以决定。
旁注:在处理价格时使用 double
是个坏主意。请改用 decimal
。