【问题标题】:Automatic LocalDate casting to string CassandraDriver自动将 LocalDate 转换为字符串 CassandraDriver
【发布时间】:2021-02-15 16:50:35
【问题描述】:

我有一个模型,在 Cassandra 和 C# 中有一堆属性,所以为了避免我不得不手动分配普通准备语句(或为我执行此操作的脚本)中的每个值,我开始使用 Mapper Component .但是,CQL dates 会自动映射到 LocalDates,它们会被序列化为具有 Date、Month 和 Year 属性的 JSON 对象,我需要一个普通字符串。

我查看了具有 DefineConvertTypesUsing 方法的 MappingConfiguration.Global,但第一个似乎没有我想要的,我什至无法实现 TypeConverter 类它期望作为后者的参数,因为它具有我从未见过的语法(而且我什至不知道它是否能完成这项工作)。

所以我想知道,CassandraDrive 中是否有任何内置选项可以实现我想要的?

如果有人想看看我的自定义 TypeConverter,我认为这是可行的:

using System;
using Cassandra;
using Cassandra.Mapping.TypeConversion;

namespace Api.Helpers
{
    public class LocalDateConverter : TypeConverter
    {
        protected override Func<TDatabase, TPoco> GetUserDefinedFromDbConverter<TDatabase, TPoco>()
        {
            Func<LocalDate, string> converter = date => 
                String.Format("{0}-{1}-{2}", date.Year, date.Month, date.Year);
            return converter;
        }

        protected override Func<TPoco, TDatabase> GetUserDefinedToDbConverter<TPoco, TDatabase>()
        {
            throw new NotImplementedException();
        }
    }

使用该方法声明语法,我不知道应该在哪里指明我希望转换器应用哪些类型。此代码因Can't convert 'System.Func&lt;Cassandra.LocalDate, string&gt;' into 'System.Func&lt;TDatabase, TPoco&gt;' 而失败。

另一个与 Cassandra 驱动程序无关的解决方案是自定义 Json 转换器,但我也在使用 OData,它使用 custom serializer

【问题讨论】:

    标签: c# cassandra


    【解决方案1】:

    试试这个:

    public class CustomTypeConverter : TypeConverter
    {
        protected override Func<TDatabase, TPoco> GetUserDefinedFromDbConverter<TDatabase, TPoco>()
        {
            if (typeof(TDatabase) == typeof(LocalDate) && typeof(TPoco) == typeof(string))
            {
                Func<LocalDate, string> func = date => date?.ToString();
                return (Func<TDatabase, TPoco>) (object) func;
            }
    
            return null;
        }
    
        protected override Func<TPoco, TDatabase> GetUserDefinedToDbConverter<TPoco, TDatabase>()
        {
            if (typeof(TDatabase) == typeof(LocalDate) && typeof(TPoco) == typeof(string))
            {
                Func<string, LocalDate> func = dateStr => dateStr == null ? null : LocalDate.Parse(dateStr);
                return (Func<TPoco, TDatabase>) (object) func;
            }
    
            return null;
        }
    }
    

    您可以通过MappingConfiguration 对象为 Mapper 或 LINQ 提供自定义转换器:

    var mc = new MappingConfiguration().ConvertTypesUsing(new CustomTypeConverter());
    
    // LINQ
    var table = new Table<Poco>(session, mc);
    
    // Mapper
    var mapper = new Mapper(session, mc);
    

    为此,您必须将属性类型更改为 string 并告诉驱动程序该属性映射到 LocalDate 列:

    public class Poco
    {
        [Cassandra.Mapping.Attributes.PartitionKey]
        [Cassandra.Mapping.Attributes.Column("project_type", Type = typeof(int))]
        public ProjectType ProjectType { get; set; }
        
        [Cassandra.Mapping.Attributes.Column("date", Type = typeof(LocalDate))]
        public string Date { get; set; }
    }
    

    如果你不使用基于属性的配置,它看起来像这样:

    var mc = new MappingConfiguration()
                .ConvertTypesUsing(new CustomTypeConverter())
                .Define(
                    new Map<Poco>()
                        .PartitionKey(s => s.ProjectType)
                        .Column(s => s.ProjectType, c => c.WithName("project_type"))
                        .Column(s => s.Date, c => c.WithDbType<LocalDate>()));
    

    您还需要在此 MappingConfiguration 实例而不是 MappingConfiguration.Global 中定义映射(除非您使用基于属性的配置)。

    请确保始终使用相同的 MappingConfiguration 实例,而不是创建多个实例,因为这是驱动程序存储生成的预编译语句的位置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      • 2016-02-23
      • 2019-07-16
      • 1970-01-01
      • 2011-04-12
      • 2017-11-02
      相关资源
      最近更新 更多