c# - 具有格式/文化的表达式树 ToString

标签 c# linq expression expression-trees

所以这是我想要实现的基本目标:

string.Format(new CultureInfo("da-DK"), "{0:n}", myDouble)

(用文化格式化数字。示例输入:1,输出:“1,00”)

上下文:我需要用一个表达式树来实现这一点,我当前的代码生成一个搜索查询,遍历产品价格,其中它应该格式化 double 。 这是我到目前为止所得到的:

 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 吗?但是我没能找到任何例子。

问题:如何使用格式/文化格式化表达式值?

最佳答案

不值得尝试为 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 查询,它将被迫评估表中的每一行。如果您将直接比较价格(即,如:c => c.Price == doubleValue)- 您将能够对该列(如果有)使用数据库索引,甚至没有索引我希望它执行得更快。但请注意,这样的比较与 Contains(...) 并不完全相同。例如,如果用户输入“1.00” - contains 将返回“111.00”、“231.00”等价格,而相等比较将只返回完全匹配的价格。在搜索价格时是否需要使用 Contains - 只有您可以决定。

旁注:在处理价格时使用 double 是个坏主意。请改用 decimal

关于c# - 具有格式/文化的表达式树 ToString,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49106725/

相关文章:

c# - Identity signIn/PasswordSignIn 返回成功,但@User.Identity.IsAuthenticated 返回 false

c# - 从 web.config 调用一个常量名称

c# - <asp :Button text jerks in IE8+

c# - 每次运行迁移脚本

linq - 通过 id 列表获取实体列表 - 按顺序

c# - 如何在 C# 中使用 where 条件从一个 DataTable 到另一个 DataTable 选择列

xslt - 编写 XPath 查询以根据属性和内容匹配元素

c# - LINQ to SQL Func 作为输入性能

c# - 我该如何清理这个 lambda?

c# - 避免通用参数