首页 > 解决方案 > 如何将数字转换为 DateTime 以在 Entity Framework LINQ 查询中进行比较?

问题描述

我在数据库中有两个实体,它们以两种不同的格式保存 DateTime;SuperLogs.EndTime是正常的DateTime,同时SuperLogs.Logs将 DateTime 保持为Year( int)、Month( int)、Day( int) 和Time( double) 的单独数字分量。我想在我的查询中做的是获取SuperLogs最新 Log 的 DateTime 大于EndTimeof的唯一实体superLogX

我有一个 C# 函数 ( GetLogDateTime) 可以将 DateTime 转换Logs为实际值DateTime,但是当传递到以下查询“System.InvalidOperationException:内部 .NET Framework 数据提供程序错误 1025”时。被抛出。

var superLogNewerThanSuperLogX = await MyDbContext.SuperLogs.SingleOrDefaultAsync
(
    superLog => superLog.Logs.Max<Log, DateTime>(GetLogDateTime) > superLogX.EndTime
);

GetLogDateTime实现如下:

private static DateTime GetLogDateTime(Log log)
{
    var time = log.Time;
    var hasTime = log.Time.HasValue;
    var hours = hasTime ? Math.Floor(time.Value / 10000) : 0;
    var minutes = hasTime ? Math.Floor(time.Value / 100) - hours * 100 : 0;

    return new DateTime
    (
        log.Year,
        log.Month,
        log.Day,
        (int)hours,
        (int)minutes,
        hasTime ? (int)(time.Value - (hours * 10000 + minutes * 100)) : 0,
        hasTime ? (int)((time.Value - Math.Truncate(time.Value)) * 1000) : 0
    );
}

我的猜测是问题的一部分是 GetLogDateTime 仅转换为 aFunc<Log, DateTime>但需要以Expression<Func<Log, DateTime>>某种方式转换为 a 。我不确定如何执行此操作,如果不可能,我还有一个数据库实现的标量函数,它执行与此方法相同的任务。

CREATE FUNCTION dbo.CreateDateTime
(
    @year SMALLINT,
    @month SMALLINT,
    @day SMALLINT,
    @time FLOAT
)
RETURNS DATETIME AS
BEGIN
    DECLARE @paddedYear VARCHAR(4) = REPLACE(STR(@year, 4), SPACE(1), '0')
    DECLARE @paddedMonth VARCHAR(2) = REPLACE(STR(@month, 2), SPACE(1), '0')
    DECLARE @paddedDay VARCHAR(2) = REPLACE(STR(@day, 2), SPACE(1), '0')
    DECLARE @hours FLOAT = ROUND(@time / 10000, 0, 1)
    DECLARE @hoursAndMinutes FLOAT = ROUND(@time / 100, 0, 1)
    DECLARE @hoursMinutesAndSeconds FLOAT = ROUND(@time, 0, 1)
    --DATETIME only supports 3 decimal places on seconds so VARCHAR 5 is the max needed for the string 0.xxx
    DECLARE @milliseconds VARCHAR(5) = CAST(@time - ROUND(@time, 0, 1) AS VARCHAR(5))
    RETURN IIF
    (
        @year IS NULL
        OR @month IS NULL
        OR @day IS NULL,
        NULL,
        CAST
        (
            IIF
            (
                @time IS NULL,          
                @paddedYear
                + @paddedMonth
                + @paddedDay,
                @paddedYear
                + @paddedMonth
                + @paddedDay
                + ' '
                --In ROUND, the final argument of 1 forces ROUND to always round down (desired here).
                + REPLACE(STR(@hours, 2), SPACE(1), '0')
                + ':'
                + REPLACE(STR(@hoursAndMinutes - @hours * 100, 2), SPACE(1), '0')
                + ':'
                + REPLACE(STR(@hoursMinutesAndSeconds - @hoursAndMinutes * 100, 2), SPACE(1), '0')
                + IIF
                (
                    @time <> @hoursMinutesAndSeconds,
                    '.'
                    + SUBSTRING(@milliseconds, 3, LEN(@milliseconds) - 2),
                    ''
                )
            )
            AS DATETIME
        )
    )
END

但是,这也不是特别有帮助,因为我似乎无法让实体框架允许我调用它!目前我能看到的唯一可行的选择是尝试将我的整个查询(比这里显示的大得多)作为存储过程移动到数据库中。还有其他方法还是我将被迫这样做?

标签: c#entity-frameworktsqldatetimeentity-framework-6

解决方案


推荐阅读