Support for [EnumMember] attribute in OrmLite enums

Hi,

I’m wondering if there is any support in OrmLite for using the [EnumMember] attribute on enum values when reading from or writing to the database.

For example:

public enum Status
{
    [EnumMember(Value = "active")]
    Active,
    
    [EnumMember(Value = "inactive")]
    Inactive
}

By default, OrmLite maps enums using either their string name or integer value. However, in my case, I need to use the values defined in the [EnumMember] attribute, since they match external data sources (e.g. "active" and "inactive").

I understand this is not supported out of the box, but is there a way to implement a custom Type Converters or similar to handle this mapping for specific enum types?

Or is there any recommended approach for handling this scenario?
I am using Firebird database.

Thanks in advance!

No they’re ServiceContract attributes which only apply to DTO/Serialization but you should be able override the default EnumConverter and override it on your DialectProvider instance, e.g:

class MyEnumConverter : EnumConverter { ... }

//...
SqliteOrmLiteDialectProvider.Instance.EnumConverter = new MyEnumConverter();
PostgreSqlDialectProvider.Instance.EnumConverter = new MyEnumConverter();
// etc

With the help of AI :face_with_peeking_eye:, I’ve come up with this solution, which seems to work fine:

public class EnumMemberConverter : EnumConverter
{
    private static readonly ConcurrentDictionary<Type, Dictionary<string, object>> ValueToEnumCache = new();
    private static readonly ConcurrentDictionary<Type, Dictionary<object, string>> EnumToValueCache = new();

    public override object ToDbValue(Type fieldType, object value)
    {
        var enumKind = GetEnumKind(fieldType);
        if (enumKind != EnumKind.EnumMember)
            return base.ToDbValue(fieldType, value);

        var map = EnumToValueCache.GetOrAdd(fieldType, type =>
            type.GetFields(BindingFlags.Public | BindingFlags.Static)
                .Where(f => f.IsLiteral)
                .ToDictionary(
                    f => f.GetValue(null)!,
                    f => f.GetCustomAttribute<EnumMemberAttribute>()?.Value ?? f.Name
                ));

        return (map.TryGetValue(value, out var strVal) ? strVal : value.ToString()) ?? string.Empty;
    }
}

Thanks!

1 Like