2016-10-05 6 views
2

Я использую protobuf-net в своем приложении для отправки зарегистрированных данных с удаленного сайта на сервер. Есть несколько типов данных - образец сообщение одного из них заключается в следующем:Как сопоставить метки C# с меткой времени PostgreSQL при использовании модели Buffer Buffer с Dapper?

message Sample { 
    required int64 recording_time = 1; // UTC Timestamp in Ticks 
    required double x_position = 2; 
    required double y_position = 3; 
    required double x_velocity = 4; 
    required double y_velocity = 5; 
} 

На сервере объект хранится в базе данных PostgreSQL. Все поля double в буфере протокола (proto2) отображаются в поля double в PostgreSQL. Поле метки времени, uint64 recording_time должно быть отображено в поле timestamp with time zone в базе данных.

Я хочу использовать тот же класс C# (с атрибутом ProtoContract) для сериализации Sample на клиенте, а также с Dapper для операций с базой данных (возможно, с расширением, например FastCRUD).

Для этого требуется отображение/преобразование между ticks (C# типа: длинный) и timestamp with time zone (C# Тип: DateTime). Каков наилучший способ реализовать это, не создавая второго класса?

Это, как я в данный момент запись объектов в базу данных:

string sql = "COPY samples (recording_time, x_position, y_position, x_velocity, y_velocity) FROM STDIN (FORMAT BINARY)"; 
using (var writer = conn.BeginBinaryImport(sql)) 
{ 
    foreach (Sample sample in sampleList) 
    { 
     writer.StartRow(); 

     writer.Write(new DateTime(sample.RecordingTime, DateTimeKind.UTC), NpgsqlTypes.NpgsqlDbType.TimestampTZ); 

     writer.Write(sample.X_Position, NpgsqlTypes.NpgsqlDbType.Double); 
     writer.Write(sample.Y_Position, NpgsqlTypes.NpgsqlDbType.Double); 
     writer.Write(sample.X_Velocity, NpgsqlTypes.NpgsqlDbType.Double); 
     writer.Write(sample.Y_Velocity, NpgsqlTypes.NpgsqlDbType.Double); 

    } 
} 

Это, как я хочу писать в базу данных:

foreach (Sample sample in sampleList) 
{ 
    conn.Insert<Sample>(sample); 
} 

и использовать соответствующий Query метод для поиска.

+0

Но вы будете использовать код C# для сохранения значения в базе данных? Если да, вы можете просто создать объект C# DateTime из этих тиков и использовать его в вызове базы данных. – Evk

+0

@Evk Да, сейчас я создаю объект DateTime и записываю в базу данных через Npgsql. Однако я хотел бы использовать Dapper (или аналогичный ORM) для извлечения объекта «Sample» из запроса. Есть ли способ записать это преобразование в конфигурацию/инициализацию Dapper? – Abir

ответ

0

Я хочу использовать тот же класс C# (с атрибутом ProtoContract) для сериализации примера на клиенте, а также с Dapper для операций с базой данных (возможно, с расширением, например FastCRUD).

Лично я думаю, что в этом проблема - попытка сделать две очень разные вещи с одним и тем же объектом. Однако! Это не обязательно невозможно. В частности, обратите внимание, что protobuf-net будет радостно работать с частными членами. Поэтому один из вариантов может быть:

public WhateverYouNeedForTheDatabase Foo { get; set; } 

[ProtoMember(someNumber)] 
private WhateverYouNeedForTheSerializer FooSerialized { 
    get { return FromX(Foo); } 
    set { Foo = ToX(value); } 
} 

Вы можете сделать подобное с Dapper, но это менее удобно. В частности, в вашем случае:

public DateTime RecordingTime { get; set; } 

[ProtoMember(1)] 
private long RecordingTimeSerialized { 
    get { return DateTimeToUnixTime(RecordingTime); } 
    set { RecordingTime = UnixTimeToDateTime(value); } 
} 

Это не требует дополнительного хранения (без дополнительных полей).

+0

Спасибо @Marc! Я не знал, что protobuf-net будет работать с частными членами. Я собираюсь проверить вашу рекомментацию с помощью моей настройки. – Abir

+0

Спасибо! Это решает проблему с одним классом. Мое приложение имеет 5 моделей. _ Возможно ли избежать написания повторяющегося кода для каждого класса? _ Один из вариантов, который я пробовал, - это определить временную метку класса {public DateTime RecordingTime {get; задавать; } [ProtoMember (1)] частный длинный RecordingTimeSerialized {...}} ', но я застрял при сопоставлении свойства' RecordingTime' объекта Timestamp' с соответствующим полем базы дат. – Abir

+0

@Arbi У меня был элемент списка пожеланий, чтобы позволить DateTime как можно дольше в protobuf, но я не реализовал его на сегодняшний день –