gpt4 book ai didi

dapper - 手动将列名与类属性映射

转载 作者:行者123 更新时间:2023-12-03 04:19:35 33 4
gpt4 key购买 nike

我是 Dapper micro ORM 的新手。到目前为止,我可以将它用于简单的 ORM 相关内容,但我无法将数据库列名称与类属性映射。

例如,我有以下数据库表:

Table Name: Person
person_id int
first_name varchar(50)
last_name varchar(50)

我有一个名为 Person 的类:

public class Person 
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

请注意,表中的列名称与我尝试将从查询结果中获取的数据映射到的类的属性名称不同。

var sql = @"select top 1 PersonId,FirstName,LastName from Person";
using (var conn = ConnectionFactory.GetConnection())
{
var person = conn.Query<Person>(sql).ToList();
return person;
}

上面的代码将不起作用,因为列名称与对象的(人)属性不匹配。在这种情况下,我可以在 Dapper 中做些什么来手动映射(例如 person_id => PersonId)列名与对象属性?

最佳答案

Dapper 现在支持自定义列到属性映射器。它通过ITypeMap来实现这一点。界面。一个CustomPropertyTypeMap Dapper 提供的类可以完成大部分工作。例如:

Dapper.SqlMapper.SetTypeMap(
typeof(TModel),
new CustomPropertyTypeMap(
typeof(TModel),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName))));

型号:

public class TModel {
[Column(Name="my_property")]
public int MyProperty { get; set; }
}

需要注意的是,CustomPropertyTypeMap 的实现要求属性存在并与列名之一匹配,否则属性将不会被映射。 DefaultTypeMap类提供标准功能并可用于更改此行为:

public class FallbackTypeMapper : SqlMapper.ITypeMap
{
private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;

public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
{
_mappers = mappers;
}

public SqlMapper.IMemberMap GetMember(string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetMember(columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException nix)
{
// the CustomPropertyTypeMap only supports a no-args
// constructor and throws a not implemented exception.
// to work around that, catch and ignore.
}
}
return null;
}
// implement other interface methods similarly

// required sometime after version 1.13 of dapper
public ConstructorInfo FindExplicitConstructor()
{
return _mappers
.Select(mapper => mapper.FindExplicitConstructor())
.FirstOrDefault(result => result != null);
}
}

有了这些,创建自定义类型映射器就变得很容易,该映射器将自动使用属性(如果存在),但否则将回退到标准行为:

public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper
{
public ColumnAttributeTypeMapper()
: base(new SqlMapper.ITypeMap[]
{
new CustomPropertyTypeMap(
typeof(T),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName)
)
),
new DefaultTypeMap(typeof(T))
})
{
}
}

这意味着我们现在可以轻松支持需要使用属性的映射的类型:

Dapper.SqlMapper.SetTypeMap(
typeof(MyModel),
new ColumnAttributeTypeMapper<MyModel>());

这是一个Gist to the full source code .

关于dapper - 手动将列名与类属性映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8902674/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com