我遇到了这个问题,我有一张购物表
Purchases(Date DateTime, Number string)
我想创建一条新记录,所以我需要Max(Number),这里的问题是Number是字符串,我试过了
Purchases.Select(X=>int.Parse(X.Number)).Max()
但它可能会抛出异常,我创建了一个自定义ToInt()
扩展程序,因此当我使用
Purchases.Select(X=>X.Number.ToInt()).Max()
它抛出一个异常,说我的ToInt()不能与linq查询一起使用,就像着名的ToString()
一样所以我的问题是:有没有办法在linq查询&中将字符串强制转换为int。同时处理异常或将自定义函数集成到linq查询!!
这是我的扩展
public static int ToInt(this string s)
{
try
{
return int.Parse(s);
}
catch
{
}
return 0;
}
答案 0 :(得分:10)
第一种方式:
var numbers = Purchases.Select(x => x.Number).ToList();
int temp;
int max = numbers.Select(n => int.TryParse(n, out temp) ? temp : 0).Max();
Console.WriteLine("Max: {0}", max);
第二种方式:
int temp2;
int max2 = Purchases.Select(x => x.Number).ToList().Select(n => int.TryParse(n, out temp2) ? temp2 : 0).Max();
Console.WriteLine("Max 2: {0}", max2);
关键是这两种方式的.ToList()
。它从数据库中获取所有string
数据,因此当您在结果上调用int.TryParse
时,数据库查询已经运行,因此它使用纯CLR代码,而不是尝试转换{{ 1}}进入SQL查询。我在我的一个Sandbox项目中创建了一个EF上下文并验证了它的工作原理。
答案 1 :(得分:2)
我不明白为什么你不想要这个例外,因为如果你的投射失败了,那就意味着你的应用程序发生了错误(或至少,所以我明白了)。我也不明白为什么要将数字作为字符串保存在数据库中。通常情况下,你会将它保存为一个数字,这样你就不必在以后处理这样的问题,如果有人试图插入错误的值,你就会在插入时失败。
但是 - 如果你想让这一行工作,你应该使用int.TryParse
,如果值成功转换,它将返回true,并将值放在'out'成员中,该成员将不在查询中。像这样:
int tmp;
Purchases.Select(X=>int.TryParse(X.Number, out tmp) ? tmp : 0).Max()
而不是“0”放置一些不会弄乱你的逻辑的默认值。