Entity Framework按日期分组求和时长遇类型转换错误求解决
解决EF分组求和时“Cannot implicitly convert type 'string' to 'long'”的错误
嘿,这个问题一眼就能定位——你犯了个很常见的类型不匹配错误!核心问题出在你的TimeSheet实体类设计上:
问题根源
看你的实体类代码,TotalHours被定义成了string类型:
public string TotalHours { get; set; }
但Sum()方法是用来对数值类型(比如int、decimal、long)做求和运算的,EF没办法直接把字符串当成数值来计算,自然就抛出了类型转换的错误。小时数本质是数值,用字符串存储本身就不符合业务数据的类型规范,这才是问题的源头。
解决方案
优先推荐第一种方案,从根源上解决问题:
方案1:修改实体类的TotalHours为数值类型
这是最合理的做法,因为小时数本身就是数值(可能包含小数,比如1.5小时)。把实体类里的TotalHours类型改成decimal(推荐,适配带小数的小时数)或者int(如果只存整数小时):
// 推荐用decimal,支持小数小时的场景 public decimal TotalHours { get; set; } // 如果业务只需要整数小时,可以用int // public int TotalHours { get; set; }
修改后,记得同步更新数据库对应的字段类型(如果用Code First,需要生成并执行迁移),这样你原来的ViewModel代码不需要任何修改就能正常运行。
方案2:在求和时手动转换类型(仅当无法修改实体类时使用)
如果因为历史遗留问题或其他限制不能修改实体类,那就在求和前把字符串转成数值类型,同时要处理转换失败的情况(比如TotalHours里存了非数字内容):
private void CalculateTime() { // 先把数据加载到内存再处理,避免EF不支持TryParse的问题 var result = context.TimeSheets.AsEnumerable() .GroupBy(o => o.StartDate) .Select(g => new { StartDate = g.Key, total = g.Sum(i => { // 尝试转换,失败则返回0(可根据需求调整默认值) decimal.TryParse(i.TotalHours, out var hours); return hours; }) }); foreach (var group in result) { Console.WriteLine("StartDate = {0} TotalHours={1}", group.StartDate, group.total); } }
如果能100%确保TotalHours里的内容都是有效的数字,也可以直接在Linq to Entities里转换(但风险较高,一旦有无效数据会直接报错):
var result = context.TimeSheets.GroupBy(o => o.StartDate) .Select(g => new { StartDate = g.Key, total = g.Sum(i => decimal.Parse(i.TotalHours)) });
总结
优先选方案1,因为数据类型匹配业务逻辑是最稳妥的,能避免后续其他操作(比如排序、比较)出现类似的类型问题。实在没办法改实体类时,再用方案2兜底。
内容的提问来源于stack exchange,提问作者Fehr Benjamin
相关产品推荐
相关产品推荐

