我试图使用Dapper和Dapper-Extensions,并将数据库中的enums序列化为string。
现在,它们被序列化为整数(在VARCHAR字段中)。
有办法这样做吗?任何我可以添加的自定义类型映射?
如果我不能挺过去的话,我可能需要搬回EF。
发布于 2016-05-17 15:44:00
感谢Marc Gravell的答复:
唯一的方法是手动执行插入操作。
还使用以下帖子:How do I perform an insert and return inserted identity with Dapper?
低于我的解决方案。
注意,自动选择工作:您可以直接使用Dapper (扩展) GetList<T>,没有映射到所需的枚举返回。
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();
}
}
}发布于 2018-07-20 07:19:06
有一种方法,我认为它更健壮,更干净。
我提供的解决方案将适用于任何枚举,但它涉及到一些额外的编码。它还包括在Dapper中添加自定义类型处理程序。但是,如果这个答案获得了一些选票,我将更改Dapper源代码,将此解决方案自动包含在类型处理中,并请求请求。
实际上,我实现了这个解决方案,并在生产中使用它。
开始吧。
首先,将用作枚举的结构(而不是类,因为结构只包含一个字符串引用):
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;
}
}现在,我们需要这个结构的类型处理程序。
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注册类型处理程序。
Dapper.SqlMapper.AddTypeHandler(typeof(Country), new CountryHandler());现在,您可以简单地使用国家作为一个“枚举”。例如:
public class Address
{
public string Street { get; set; }
public Country Country { get; set; }
}
var addr = new Address { Street = "Sesamestreet", Country = Country.GB };当然,它的缺点是枚举不是由整数在内存中支持,而是由字符串支持。
发布于 2021-04-30 01:21:50
我的技术很简单,但让我用真正的吊床。而且它是通用的,所以我不需要写很多次。
有一个不可变的结构来包装枚举值。它只有一个属性和隐式转换,外加一个通用的自定义类型处理程序。
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,当然可以删除它
下面是一个例子:
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;}
}调用代码可以使用普通枚举值。
var item = new HolidayScheduleItem()
{
Holiday = Holiday.MlkDay,
When = new DateTime(2021, 1, 18)
};它适用于普通Dapper或Dapper.Contrib:
await conn.ExecuteAsync("INSERT HolidayScheduleItem ([Holiday], [When])
VALUES(@Holiday, @When)", item);
await conn.InsertAsync(item);

https://stackoverflow.com/questions/37264655
复制相似问题