Linq-to-Entities SqlFunctions:如何从int转换为double?还是小数?

时间:2014-04-28 16:34:27

标签: c# .net entity-framework linq-to-entities sql-function

我正在尝试使用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))));

2 个答案:

答案 0 :(得分:1)

在v.UpVote上添加一个转换为double。 LINQ转换器应插入适当的CONVERT指令。

答案 1 :(得分:1)

该异常表明问题与执行操作有关,而不是转换涉及的类型的问题。在SQL中使用LOG10将在传递负数时抛出此异常(尝试它:SELECT LOG10(-1))。如果SqlFunctions.DateDiff返回一个负数(可以使用Created日期),则查询将失败。

我猜你只需要切换DateTime.Todayv.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的数字需要以某种方式处理。