我正在尝试使用Linq to Entities对一些文章进行排序。我正在使用System.Data.Objects.SqlClient.SqlFunctions。这就是我想要的:
this.Queryable = this.Queryable
.OrderByDescending(v => v.UpVote + SqlFunctions.Log10(
SqlFunctions.DateDiff("d", DateTime.Today, v.Created)));
但是,这不起作用,因为DateDiff返回int?
而Log10需要double?
或decimal?
。
我找不到在SqlFunctions中执行此操作的转换函数。我尝试将它乘以1.0,或者将其投射,但我得到以下错误:
System.Data.Entity.Core.EntityCommandExecutionException:错误 从商店提供商的数据阅读器读取时发生。见 内部异常细节。 ---> System.Data.SqlClient.SqlException: 发生了无效的浮点运算。
如何使用SqlFunction将int?
转换为double?
或decimal?
?
解答:
基于Ocelot20的响应,我切换了参数,并在创建日添加了一天,因此它永远不会产生负数或0输入,这是导致错误的原因。我还需要将UpVote强制转换为double。这就是工作版本的样子:
var date = DateTime.Today.AddDays(1);
this.Queryable = this.Queryable
.OrderByDescending(v => (double)v.UpVote - SqlFunctions.Log10(Math.Abs((double)
SqlFunctions.DateDiff("d", date, v.Created))));
答案 0 :(得分:1)
在v.UpVote上添加一个转换为double。 LINQ转换器应插入适当的CONVERT指令。
答案 1 :(得分:1)
该异常表明问题与执行操作有关,而不是转换涉及的类型的问题。在SQL中使用LOG10
将在传递负数时抛出此异常(尝试它:SELECT LOG10(-1)
)。如果SqlFunctions.DateDiff
返回一个负数(可以使用Created
日期),则查询将失败。
我猜你只需要切换DateTime.Today
和v.Created
就可以使用适当的投射来实现:
this.Queryable
.Select(v => v.UpVote +
SqlFunctions.Log10(
(double?)SqlFunctions.DateDiff("d", v.Created, DateTime.Today));
或者如果v.Created
恰好包含未来日期或者存在一些负时差,您可以使用Math.Abs
来确保它始终是正面的:
this.Queryable
.Select(v => v.UpVote +
SqlFunctions.Log10(
(double?)Math.Abs(
SqlFunctions.DateDiff("d", DateTime.Today, v.Created)));
修改 - 除了使用负数失败外,LOG10
将在提供0时失败。您可以过滤掉0,或将其忽略为修饰符:
from v in this.Queryable
let dayDiff = SqlFunctions.DateDiff("d", v.Created, DateTime.Today)
let voteWeight = dayDiff == 0 ?
0 :
SqlFunctions.Log10((double?)dayDiff)
select v.UpVote + voteWeight
没有测试这个确切的查询,但它的要点是小于或等于0的数字需要以某种方式处理。