【问题标题】:How to map a C# enum to a Cassandra field using Datastax C# Driver?如何使用 Datastax C# 驱动程序将 C# 枚举映射到 Cassandra 字段?
【发布时间】:2017-03-24 09:08:18
【问题描述】:

我想使用 Datastax C# 驱动程序(.Net Framework 4.6.1、Datastax C# 驱动程序 3.0.8)在 Cassandra 中保存和检索 POCO 对象

例子:

public enum DocumentState
{
    New = 0,
    Approved = 1,
    Rejected = 2
}

public class DocumentReadModel
{
    public Guid DocumentId { get; set; }
    public DocumentState State { get; set; }
}

在 Cassandra 中持久保存该对象的最佳方法是什么?

我的方法似乎不起作用。

现在我尝试在 Cassandra 中将其保存为 int:

create table if not exists documentreadmodel (
        documentid uuid PRIMARY KEY,
        state int);

还使用了 Datastax 驱动程序提供的映射配置,代码如下:

MappingConfiguration.Global.Define(
    new Map<DocumentReadModel>()
            .TableName("documentreadmodel")
            .PartitionKey(o => o.MerchantId)
            .Column(o => o.State, c =>     c.WithName("state").WithDbType<int>()));

但我仍然遇到异常:

Cassandra.InvalidTypeException: 
Unknown Cassandra target type for CLR type ValueObjects.DocumentState

我应该在 Cassandra 中使用另一种 int 类型吗? 以不同方式配置驱动程序?

【问题讨论】:

  • hm...映射正确,你用的是Mapper.Insert()方法吗?确保在调用映射器方法之前定义了映射。我刚刚向 repo 推送了一个集成测试,涵盖了您描述的类似场景:github.com/datastax/csharp-driver/pull/268
  • 谢谢。我通过我公司自己的包装器使用驱动程序,因此出现了问题。

标签: c# enums cassandra datastax


【解决方案1】:

我通过更新全局配置以使用 For 找到了解决方案

我正在使用 .NET 4.5.2 CassandraCSharpDriver 3.3.2

尝试更新您的配置以使用“For”

MappingConfiguration.Global.Define(
For<DocumentReadModel>()
        .TableName("documentreadmodel")
        .PartitionKey(o => o.MerchantId)
        .Column(o => o.State, c => c.WithName("state").WithDbType<int>()));

【讨论】:

    【解决方案2】:

    这是一个相当古老的问题,但可能会帮助遇到这些问题的其他人......

    要将 Enum 保存到 cassandra,您需要定义一个转换器函数以将 Enum 转换为 Int。 应该是这样的:

    public class MyTypeConverter : TypeConverter
    {
        protected override Func<TDatabase, TPoco> GetUserDefinedFromDbConverter<TDatabase, TPoco>()
        {
            if (typeof(TDatabase) == typeof(Int32) && typeof(TPoco) == typeof(DocumentState))
            {
                Func<Int32, DocumentState> func = documentState=> (DocumentState)documentState;
                return (Func<TDatabase, TPoco>)(object)func;
            }
    
            return null;
        }
    
        protected override Func<TPoco, TDatabase> GetUserDefinedToDbConverter<TPoco, TDatabase>()
        {
            if (typeof(TDatabase) == typeof(Int32) && typeof(TPoco) == typeof(DocumentState))
            {
                Func<Provider, Int32> func = documentState=>
                        ((Int32)documentState);
    
                return (Func<TPoco, TDatabase>)(object)func;
            }
    
            return null;
        }
    }
    

    然后在定义你的表时你应该注册转换器:

            var mapping = new MyMapping();
            var table = new Table<T>(session, new MappingConfiguration()
                .ConvertTypesUsing(new MyTypeConverter())
                .Define(mapping));
    

    查询 cassandra 时,驱动程序使用序列化程序(不是 TypeConverter),并且它们不支持 Enums。所以你必须用 Int 替换 Enum。我使用 LINQ,它看起来像这样:

            int documentStateInt = (int)documentState;
            Expression<Func<DocumentReadModel, bool>> predicate;
            predicate= drm => (int)drm.State == documentStateInt;
    
            return table.Where(predicate).ExecuteAsync();
    

    *使用驱动程序版本 3.16

    【讨论】:

      猜你喜欢
      • 2017-03-28
      • 2017-08-22
      • 2017-08-04
      • 2014-03-27
      • 2020-11-23
      • 2016-01-22
      • 1970-01-01
      • 2017-10-10
      • 1970-01-01
      相关资源
      最近更新 更多