You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过NHibernate将C#枚举的EnumMember值(含空格)存入数据库

让NHibernate存储EnumMember特性指定的枚举值

要实现这个需求,你需要自定义一个NHibernate的用户类型——因为默认的枚举映射逻辑不会识别EnumMember特性。下面是具体的实现步骤,亲测可用:

1. 创建自定义枚举字符串类型

这个类型会重写NHibernate默认的枚举字符串处理逻辑,专门读取EnumMember特性里的值,同时支持反向从数据库字符串映射回枚举:

using System;
using System.Reflection;
using System.Runtime.Serialization;
using NHibernate.Type;

public class EnumMemberStringType<TEnum> : EnumStringType<TEnum> 
    where TEnum : struct, Enum
{
    public EnumMemberStringType() : base(typeof(TEnum))
    {
    }

    // 写入数据库时,优先取EnumMember的Value
    public override object GetValue(object enumValue)
    {
        if (enumValue == null)
            return null;

        var memberInfo = typeof(TEnum).GetMember(enumValue.ToString())[0];
        var enumMemberAttr = memberInfo.GetCustomAttribute<EnumMemberAttribute>();
        
        // 有EnumMember特性就用它的值,没有就 fallback到枚举名称
        return enumMemberAttr != null ? enumMemberAttr.Value : enumValue.ToString();
    }

    // 从数据库读取时,根据字符串反向匹配枚举值
    public override object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
    {
        var dbValue = base.NullSafeGet(rs, names, owner);
        if (dbValue == null)
            return null;

        var stringValue = dbValue.ToString();
        // 遍历枚举字段,找到对应EnumMember值的项
        foreach (var field in typeof(TEnum).GetFields())
        {
            var enumMemberAttr = field.GetCustomAttribute<EnumMemberAttribute>();
            if (enumMemberAttr != null && enumMemberAttr.Value.Equals(stringValue, StringComparison.Ordinal))
            {
                return Enum.Parse(typeof(TEnum), field.Name);
            }
        }

        // 没找到匹配的EnumMember,就用默认逻辑解析枚举名称
        return Enum.Parse(typeof(TEnum), stringValue);
    }
}

2. 在NHibernate映射中使用这个自定义类型

根据你用的映射方式选择对应的写法:

Fluent NHibernate 写法

Map(x => x.Rating).CustomType<EnumMemberStringType<AppraisalRating>>();

XML 映射写法(如果使用XML配置)

<property name="Rating" type="你的命名空间.EnumMemberStringType`1[[你的命名空间.AppraisalRating, 你的程序集名称]], 你的程序集名称" />

关键注意点

  • 确保枚举的每个值都配置了EnumMember特性,否则会自动 fallback 到枚举名称存储
  • 这个类型会完整保留EnumMember值里的空格,完全满足你和其他系统集成的要求
  • 测试时记得验证:写入数据库后字段值是"N S"/"N R",读取时能正确映射回对应的枚举项

内容的提问来源于stack exchange,提问作者ViqMontana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:31:56