我刚开始使用Dapper.Contrib来帮助我进行插入和获取,但由于我的枚举存储为数据库中的字符串(由于多种原因)我遇到插入问题。 Dapper在读取时与字符串枚举无缝地工作,但插入将始终将序数值放入数据库中。
我已经为Dapper读了很多提案,并且打开了很多问题,但没有找到可行的解决方案。我的简化类如下所示:
public class Person {
public long Id { get; set; }
public string Name { get; set; }
public Gender Gender { get; set; }
}
public enum Gender { Female, Male, TransWoman, TransMan }
我原以为我可以配置Dapper.Contrib来使用枚举名而不是序数值来发出插入,这样代码可以神奇地工作并在varchar(20)数据库字段中插入'Male'性别:
void InsertPersonFelipe(SqlConnection conn) {
var person = new Person { Name = "Felipe", Gender = Gender.Male };
conn.Insert(person);
}
有没有办法为typeof(Gender)
添加自定义映射?
或者,更好的是,Dapper.Contrib是否提供配置以使其使用枚举名称而不是其序数值?
答案 0 :(得分:0)
我编写了一个扩展方法来处理将枚举转换为字符串,并考虑了Dapper.Contrib中的 Table 和 Computed 属性。如果您不想引用Dapper.Contrib,则可以轻松地将其删除。
用法:
using (var sql = new SqlConnection(_connString))
{
sql.Open();
sql.InsertB(person);
}
扩展方法:
public static long InsertB<T>(this SqlConnection sqlConnection, T obj)
{
Dictionary<string, object> propertyValuesMap = new Dictionary<string, object>();
var columns = new StringBuilder();
var values = new StringBuilder();
var tableName = ((TableAttribute)obj.GetType().GetCustomAttribute(typeof(TableAttribute))).Name;
var relevantProperties = obj.GetType().GetProperties().Where(x => !Attribute.IsDefined(x, typeof(ComputedAttribute))).ToList();
for (int i = 0; i < relevantProperties.Count(); i++)
{
object val = null;
var propertyInfo = relevantProperties[i];
if (propertyInfo.PropertyType.IsEnum)
{
val = Enum.GetName(propertyInfo.PropertyType, propertyInfo.GetValue(obj));
}
else
{
val = propertyInfo.GetValue(obj);
}
propertyValuesMap.Add(propertyInfo.Name, val);
var propName = i == relevantProperties.Count() - 1 ? $"{propertyInfo.Name}" : $"{propertyInfo.Name},";
columns.Append(propName);
values.Append($"@{propName}");
}
return sqlConnection.Execute($"Insert Into {tableName} ({columns}) values ({values})", propertyValuesMap);
}
答案 1 :(得分:0)
我将 Dan 的答案改写为更现代的 C# 并且不尝试插入 ID(因为我有自动递增标识列),以及使用表名而不是查看属性。
public static long InsertB<T>(this SqlConnection sqlConnection, T obj, string tableName)
{
Dictionary<string, object> propertyValuesMap = new Dictionary<string, object>();
var columnList = new List<String>();
var valueList = new List<String>();
var relevantProperties = obj.GetType().GetProperties().Where(x => !Attribute.IsDefined(x, typeof(ComputedAttribute))).ToList();
foreach (var propertyInfo in relevantProperties)
{
if (propertyInfo.Name.ToLower() == "id") continue; // do not try to insert id
var val = propertyInfo.PropertyType.IsEnum
? Enum.GetName(propertyInfo.PropertyType, propertyInfo.GetValue(obj))
: propertyInfo.GetValue(obj);
propertyValuesMap.Add(propertyInfo.Name, val);
columnList.Add(propertyInfo.Name);
valueList.Add($"@{propertyInfo.Name}");
}
return sqlConnection.Execute($"Insert Into {tableName} ({String.Join(", ", columnList)}) values ({String.Join(", ", valueList)})", propertyValuesMap);
}