在Select语句中将DateTime转换为Unix时间戳?

时间:2015-02-12 13:41:15

标签: c# sql-server entity-framework datetime timestamp

我有一个包含数百万个归档值行的数据库表,这些行包含一个值(单个),两个整数id字段和一个datetime字段(以及一些与我想要构建的缓存无关的其他字段) 。表结构是固定的,我无法改变它。现在我想将所有行读入一个简单类的对象数组中,我希望将其保存在内存中以用于缓存。

为了保持低内存消耗,我想使用unix时间戳而不是datetime对象。这也很有用,因为连续使用此缓存的前端图表等本身也适用于Unix时间戳。

对于缓存创建,我想直接选择 ArchiveElement 。这适用于大多数领域,但我不知道如何在select语句中动态创建Unix时间戳:

ArchiveCache = db.ArchiveValues.Select(x => new ArchiveElement() {
    DataPointId = (UInt16)x.DataPointId,
    StationId = (UInt16)x.StationId,
    Value = (Single)x.Value,
    DateValue = x.DateValue // <-- Here I want to cast into Unix Timestamp
});

这是ArchiveElement类:

public class ArchiveElement
{
    public UInt32 DateValue;
    public UInt16 DataPointId;
    public UInt16 StationId;
    public Single Value;
}

我的应用程序中有一个函数可以将DateTime转换为Unix TimeStamp,但这在select语句的范围内不起作用。所以我需要找到另一种方式。

一种方法是在.ToList()语句之前插入一个.Select(..),这样我就可以访问我自己的函数,但这将是一个丑陋的解决方法,因为它从中获取了大量不必要的字段DB。

有没有办法以某种方式“转换”日期时间?

2 个答案:

答案 0 :(得分:2)

首先你声明Unix Epoch时间:

var unixEpoch = DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

现在在您的Select中,只需从日期值中减去一个时代,该日期值为TimeSpan类型,您可以从中获得TotalSeconds这是您需要的值:

ArchiveCache = db.ArchiveValues.Select(x => new ArchiveElement() {
    DataPointId = (UInt16)x.DataPointId,
    StationId = (UInt16)x.StationId,
    Value = (Single)x.Value,
    DateValue = (x.DateValue - unixEpoch).TotalSeconds
});

注意:这假设您的DateValue属性为双倍,您可能需要将其投放到long

修改

为了应对实体框架,这可能有效:

ArchiveCache = db.ArchiveValues.Select(x => new ArchiveElement() {
    DataPointId = (UInt16)x.DataPointId,
    StationId = (UInt16)x.StationId,
    Value = (Single)x.Value,
    DateValue =  SqlFunctions.DateDiff("ss", unixEpoch, x.DateValue)
});

这可能需要System.Data.Entity.SqlServer的参考/导入。

答案 1 :(得分:0)

DATEDIFF(SECOND,{d '1970-01-01'}, GETUTCDATE())

这将返回sql中的unix秒。