首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Dapper和Enum作为字符串

Dapper和Enum作为字符串
EN

Stack Overflow用户
提问于 2016-05-16 23:13:49
回答 6查看 17.1K关注 0票数 16

我试图使用DapperDapper-Extensions,并将数据库中的enums序列化为string

现在,它们被序列化为整数(在VARCHAR字段中)。

有办法这样做吗?任何我可以添加的自定义类型映射?

如果我不能挺过去的话,我可能需要搬回EF。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2016-05-17 15:44:00

感谢Marc Gravell的答复:

唯一的方法是手动执行插入操作。

还使用以下帖子:How do I perform an insert and return inserted identity with Dapper?

低于我的解决方案。

注意,自动选择工作:您可以直接使用Dapper (扩展) GetList<T>,没有映射到所需的枚举返回。

代码语言:javascript
复制
public enum ComponentType
{
    First,
    Second,
    Third
}

public class Info
{
    public int Id { get; set; }
    public ComponentType InfoComponentType { get; set; }

    public static void SaveList(List<Info> infoList)
    {
        string ConnectionString = GetConnectionString();

        using (SqlConnection conn = new SqlConnection(ConnectionString))
        {
            conn.Open();

            foreach (Info info in infoList)
            {
                string sql = @"INSERT INTO [Info] ([InfoComponentType]) 
                               VALUES (@InfoComponentType);
                               SELECT CAST(SCOPE_IDENTITY() AS INT)";

                int id = conn.Query<int>(sql, new
                {
                    InfoComponentType = info.InfoComponentType.ToString()
                }).Single();

                info.Id = id;
            }

            conn.Close();
        }
    }
}
票数 5
EN

Stack Overflow用户

发布于 2018-07-20 07:19:06

有一种方法,我认为它更健壮,更干净。

我提供的解决方案将适用于任何枚举,但它涉及到一些额外的编码。它还包括在Dapper中添加自定义类型处理程序。但是,如果这个答案获得了一些选票,我将更改Dapper源代码,将此解决方案自动包含在类型处理中,并请求请求。

实际上,我实现了这个解决方案,并在生产中使用它。

开始吧。

首先,将用作枚举的结构(而不是类,因为结构只包含一个字符串引用):

代码语言:javascript
复制
public struct Country
{
    string value;

    public static Country BE => "BE";
    public static Country NL => "NL";
    public static Country DE => "DE";
    public static Country GB => "GB";

    private Country(string value)
    {
        this.value = value;
    }

    public static implicit operator Country(string value)
    {
        return new Country(value);
    }

    public static implicit operator string(Country country)
    {
        return country.value;
    }
}

现在,我们需要这个结构的类型处理程序。

代码语言:javascript
复制
public class CountryHandler : SqlMapper.ITypeHandler
{
    public object Parse(Type destinationType, object value)
    {
        if (destinationType == typeof(Country))
            return (Country)((string)value);
        else return null;
    }

    public void SetValue(IDbDataParameter parameter, object value)
    {
        parameter.DbType = DbType.String;
        parameter.Value = (string)((dynamic)value);
    }
}

在应用程序启动的某个地方,我们必须向Dapper注册类型处理程序。

代码语言:javascript
复制
Dapper.SqlMapper.AddTypeHandler(typeof(Country), new CountryHandler());

现在,您可以简单地使用国家作为一个“枚举”。例如:

代码语言:javascript
复制
public class Address
{
     public string Street { get; set; }
     public Country Country { get; set; }
}

var addr = new Address { Street = "Sesamestreet", Country = Country.GB };

当然,它的缺点是枚举不是由整数在内存中支持,而是由字符串支持。

票数 17
EN

Stack Overflow用户

发布于 2021-04-30 01:21:50

我的技术很简单,但让我用真正的吊床。而且它是通用的,所以我不需要写很多次。

有一个不可变的结构来包装枚举值。它只有一个属性和隐式转换,外加一个通用的自定义类型处理程序。

代码语言:javascript
复制
public readonly struct DapperableEnum<TEnum> where TEnum : Enum
{
    [JsonConverter(typeof(StringEnumConverter))]
    public TEnum Value { get; }

    static DapperableEnum()
    {
        Dapper.SqlMapper.AddTypeHandler(typeof(DapperableEnum<TEnum>), new DapperableEnumHandler<TEnum>());
    }

    public DapperableEnum(TEnum value)
    {
        Value = value;
    }
    public DapperableEnum(string description)
    {
        Value = EnumExtensions.GetValueByDescription<TEnum>(description);
    }

    public static implicit operator DapperableEnum<TEnum>(TEnum v) => new DapperableEnum<TEnum>(v);
    public static implicit operator TEnum(DapperableEnum<TEnum> v) => v.Value;
    public static implicit operator DapperableEnum<TEnum>(string s) => new DapperableEnum<TEnum>(s);
}

public class DapperableEnumHandler<TEnum> : SqlMapper.ITypeHandler
    where TEnum : Enum
{
    public object Parse(Type destinationType, object value)
    {
        if (destinationType == typeof(DapperableEnum<TEnum>))
        {
            return new DapperableEnum<TEnum>((string)value);
        }
        throw new InvalidCastException($"Can't parse string value {value} into enum type {typeof(TEnum).Name}");
    }

    public void SetValue(IDbDataParameter parameter, object value)
    {
        parameter.DbType = DbType.String;
        parameter.Value =((DapperableEnum<TEnum>)value).Value.GetDescription();
    }
}

我使用静态构造函数在启动时自动注册类型处理程序。

我使用GetDescription / GetValueByDescription (与this answer相同的思想)来支持不会有效的C#枚举值的字符串。如果您不需要这个特性,ToString和Enum.Parse就可以正常工作了。

JsonConverter属性也使Json.Net使用字符串值。如果您不使用Json.Net,当然可以删除它

下面是一个例子:

代码语言:javascript
复制
enum Holiday
{
    Thanksgiving,
    Christmas,
    [Description("Martin Luther King, Jr.'s Birthday")]
    MlkDay,
    Other,
}

class HolidayScheduleItem : IStandardDaoEntity<HolidayScheduleItem>
{
    public DapperableEnum<Holiday> Holiday {get; set;}
    public DateTime When {get; set;}
}

调用代码可以使用普通枚举值。

代码语言:javascript
复制
        var item = new HolidayScheduleItem()
        {
            Holiday = Holiday.MlkDay,
            When = new DateTime(2021, 1, 18)
        };

它适用于普通Dapper或Dapper.Contrib:

代码语言:javascript
复制
        await conn.ExecuteAsync("INSERT HolidayScheduleItem ([Holiday], [When])
           VALUES(@Holiday, @When)", item);
        await conn.InsertAsync(item);

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37264655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档