将DateTime保存到Cassandra Date列 [英] Saving a DateTime to Cassandra Date column

查看:77
本文介绍了将DateTime保存到Cassandra Date列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Cassandra .NET驱动程序文档令人难以置信,我试图拼凑一些功能,但是我浪费大量时间试图从发现的Java文档中更改代码。

Cassandra .NET driver documentation is unbelievably poor, I'm trying to scrap together something functional but I waste so much time trying to change code from Java documents that I found.

我正在尝试使用Cassandra驱动程序将数据写入一个简单的表中。该表格已经存在,并且里面有日期。我创建了一个映射并添加了一些列。以下是演示的简化版本:

I am trying to write data to a simple table using Cassandra driver. The table already exists and there's date inside. I have created a mapping and added some columns. Here's a cut-off version to demonstrate:

For<Profile>().TableName("profiles")
    .PartitionKey(p => p.IntegerId)
    .Column(p => p.IntegerId, cm => cm.WithName("profileid"))
    .Column(p => p.BirthDate, cm => cm.WithName("dateofbirth"))

更多列

然后通过简单的通用方法完成保存:

Then saving is done from a simple generic method:

public async Task<bool> Add<T>(T item) where T : EntityBase, new()
{
    await _mapper.InsertIfNotExistsAsync(item);
}

这里还有更多代码,但相关部分在这里。重要的是我正在使用InsertIfNotExists并使用与基础实体一起使用的通用方法。

Again there's more code there, but the relevant parts are here. What's important is that I'm using InsertIfNotExists and using generic method that works with a base entity.

dateofbirth 列在Cassandra中,日期类型。
当我运行Insert方法时,我得到一个例外,即Date的长度应该是4个字节而不是8个字节(我想我需要切断DateTime的时间部分)。

dateofbirth column in Cassandra is of type Date. When I run the Insert method I get exception that the length of Date should be 4 bytes instead of 8 (I assume I need to cut off the time part of the DateTime).

我尝试在映射上使用WithType并创建一个TypeSerializer,类似于在,但是没有运气。
任何人都有可以将这种类型(以及其他类型)保存到Cassandra的有效代码吗?

I tried using WithType on the mapping and creating a TypeSerializer similar to what was described at this question, but had no luck. Anyone has a working code that saves this type (and possibly other types) to Cassandra?

以下是从互联网改编的日期编解码器的代码,以及使用方式,可能(非常)错误:

Here's the code for the date codec that was adapted from the internet, and how it was used, it might be (very) wrong:

public class DateCodec : TypeSerializer<DateTime>
{
    private static TypeSerializer<LocalDate> _innerSerializer;

    public DateCodec(TypeSerializer<LocalDate> serializer)
    {
        _innerSerializer = serializer;
        TypeInfo = new CustomColumnInfo("LocalDate");
    }

    public override IColumnInfo TypeInfo { get; }

    public override DateTime Deserialize(ushort protocolVersion, byte[] buffer, int offset, int length, IColumnInfo typeInfo)
    {
        var result = _innerSerializer.Deserialize(protocolVersion, buffer, offset, length, typeInfo);
        return new DateTime(result.Year, result.Month, result.Day);
    }

    public override ColumnTypeCode CqlType { get; }

    public override byte[] Serialize(ushort protocolVersion, DateTime value)
    {
        return _innerSerializer.Serialize(protocolVersion, new LocalDate(value.Year, value.Month, value.Day));
    }
}

用法:

TypeSerializerDefinitions definitions = new TypeSerializerDefinitions();
definitions.Define(new DateCodec(TypeSerializer.PrimitiveLocalDateSerializer));

var cluster = Cluster.Builder()
    .AddContactPoints(...)
    .WithCredentials(...)
    .WithTypeSerializers(definitions)
    .Build();


推荐答案

C#驱动程序使用 LocalDate 类代表Cassandra中的日期,因此要么需要更改您的 dateofbirth 声明即可使用

C# driver uses LocalDate class to represent date from Cassandra, so either need to change your declaration of dateofbirth to use it, or develop corresponding codec.

您可以查看C#驱动程序的日期和时间表示文档:> https://docs.datastax.com/zh-CN/developer/csharp-driver/3.5/features/datatypes/ datetime /

You can check the documentation on date and time representation for the C# driver: https://docs.datastax.com/en/developer/csharp-driver/3.5/features/datatypes/datetime/

使用代码示例更新问题后进行更新:

Update after update of the question with code sample:

定义表&插入示例数据:

Define table & insert sample data:

cqlsh> create table test.dt(id int primary key, d date);
cqlsh> insert into test.dt(id, d) values(1, '2018-05-17');
cqlsh> insert into test.dt(id, d) values(2, '2018-05-16');
cqlsh> insert into test.dt(id, d) values(3, '2018-05-15');

为我转换的作品如下:

public class DateCodec : TypeSerializer<DateTime>
{
    private static readonly TypeSerializer<LocalDate> serializer = 
         TypeSerializer.PrimitiveLocalDateSerializer;

    public override ColumnTypeCode CqlType
    {
        get { return ColumnTypeCode.Date; }
    }

    public DateCodec() { }

    public override DateTime Deserialize(ushort protocolVersion, byte[] buffer, 
         int offset, int length, IColumnInfo typeInfo)
    {
        var result = serializer.Deserialize(protocolVersion, buffer,
                offset, length, typeInfo);
        return new DateTime(result.Year, result.Month, result.Day);
    }

    public override byte[] Serialize(ushort protocolVersion, DateTime value)
    {
        return serializer.Serialize(protocolVersion, 
            new LocalDate(value.Year, value.Month, value.Day));
    }
}

主程序:

TypeSerializerDefinitions definitions = new TypeSerializerDefinitions();
definitions.Define(new DateCodec());

var cluster = Cluster.Builder()
         .AddContactPoints("localhost")
         .WithTypeSerializers(definitions)
         .Build();
var session = cluster.Connect();
var rs = session.Execute("SELECT * FROM test.dt");
foreach (var row in rs)
{
    var id = row.GetValue<int>("id");
    var date = row.GetValue<DateTime>("d");
    Console.WriteLine("id=" + id + ", date=" + date);
}

var pq = session.Prepare("insert into test.dt(id, d) values(?, ?);");
var bound = pq.Bind(10, new DateTime(2018, 04, 01));
session.Execute(bound);

给出以下结果:

id=1, date=5/17/18 12:00:00 AM
id=2, date=5/16/18 12:00:00 AM
id=3, date=5/15/18 12:00:00 AM

然后从 cqlsh

cqlsh> SELECT * from test.dt ;

 id | d
----+------------
 10 | 2018-04-01
  1 | 2018-05-17
  2 | 2018-05-16
  3 | 2018-05-15

这篇关于将DateTime保存到Cassandra Date列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆