如何通过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
相关产品推荐
相关产品推荐

