2015-02-12 1 views
1

У меня есть таблица базы данных с миллионами заархивированных строк значений, которые состоят из значения (одиночного), двух целочисленных полей id и поля datetime (и некоторых других полей, которые не имеют отношения к кешу, который я хочу построить). Структура таблицы исправлена, я не могу ее изменить. Теперь я хочу прочитать все строки в массив объектов простого класса, который я хочу сохранить в памяти для кеширования.Вставить DateTime в Unix Timestamp в инструкции Select?

Чтобы снизить потребление памяти, я хочу использовать временную метку unix вместо объекта datetime. Это также полезно, потому что интерфейсные диаграммы и т. Д., Которые будут последовательно работать с этим кешем, также изначально работают с отметками времени Unix.

Для создания кеша я хочу выбрать непосредственно в ArchiveElement. Это хорошо работает для большинства полей, но я не знаю, как создать Отметка времени 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(..) заявлением, так что у меня есть доступ к моей собственной функции, но это было бы некрасиво обходным путь, как он получает много полей из ненужной БД.

Есть ли способ каким-то образом преобразовать дату-время "на место"?

+0

Получает ли он много ненужных полей? Похоже, вы пытаетесь вытащить всю таблицу в любом случае. – Jonesopolis

+0

В таблице DB есть еще несколько полей, которые я здесь не упоминал, просто чтобы это было просто. – Robert

+0

Что именно вы подразумеваете под отметкой времени Unix? Вы имеете в виду эпоху, например 1423748783? – DavidG

ответ

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.

Редактировать

Чтобы справиться с Entity Framework, это может работать:

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.

+0

Это генерирует System.ArgumentException (* DbArithmeticExpression *). – Robert

+0

А, я забыл, что это была платформа Entity Framework. Вы можете сделать 'ToList()' перед 'Select'? – DavidG

+0

Если бы я сделал это, я мог бы также использовать свою собственную функцию ;-) – Robert

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

Это вернет секунды unix в sql.

Смежные вопросы