Dapper中数据表的字段(列)与实体属性不一致时,如何手动配置它们之间的映射?
NET[C#]Dapper中数据表的字段(列)与实体属性不一致时,如何手动配置它们之间的映射?
问题描述
比如有如下的数据表结构:
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; }
}
在C#程序中,使用Dapper做查询时,如何配置数据表字段(列)和实体类属性之间的映射呢?
方案一
var sql = @"select top 1 person_id PersonId, first_name FirstName, last_name LastName from Person";
using (var conn = ConnectionFactory.GetConnection())
{
var person = conn.Query<Person>(sql).ToList();
return person;
}
方案二
使用 ColumnAttribute 属性
完整的代码片段:
namespace YourNamespace
{
/// <summary>
/// Uses the Name value of the <see cref="ColumnAttribute"/> specified to determine
/// the association between the name of the column in the query results and the member to
/// which it will be extracted. If no column mapping is present all members are mapped as
/// usual.
/// </summary>
/// <typeparam name="T">The type of the object that this association between the mapper applies to.</typeparam>
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))
})
{
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ColumnAttribute : Attribute
{
public string Name { get; set; }
}
public class FallbackTypeMapper : SqlMapper.ITypeMap
{
private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;
public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
{
_mappers = mappers;
}
public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
foreach (var mapper in _mappers)
{
try
{
ConstructorInfo result = mapper.FindConstructor(names, types);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetConstructorParameter(constructor, columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetMember(columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public ConstructorInfo FindExplicitConstructor()
{
return _mappers
.Select(mapper => mapper.FindExplicitConstructor())
.FirstOrDefault(result => result != null);
}
}
}
调用方法:
public class Person
{
[Column(Name="person_id")]
public int PersonId { get; set; }
[Column(Name="first_name")]
public string FirstName { get; set; }
[Column(Name="last_name")]
public string LastName { get; set; }
}
方案三
使用 CustomPropertyTypeMap 自定义属性类型映射类,如:
public class ColumnMap
{
private readonly Dictionary<string, string> forward = new Dictionary<string, string>();
private readonly Dictionary<string, string> reverse = new Dictionary<string, string>();
public void Add(string t1, string t2)
{
forward.Add(t1, t2);
reverse.Add(t2, t1);
}
public string this[string index]
{
get
{
// Check for a custom column map.
if (forward.ContainsKey(index))
return forward[index];
if (reverse.ContainsKey(index))
return reverse[index];
// If no custom mapping exists, return the value passed in.
return index;
}
}
}
配置列映射关系
var columnMap = new ColumnMap();
columnMap.Add("Field1", "Column1");
columnMap.Add("Field2", "Column2");
columnMap.Add("Field3", "Column3");
SqlMapper.SetTypeMap(typeof (MyClass), new CustomPropertyTypeMap(typeof (MyClass), (type, columnName) => type.GetProperty(columnMap[columnName])));
方案四
查询时使用LINQ
var sql = @"select top 1 person_id, first_name, last_name from Person";
using (var conn = ConnectionFactory.GetConnection())
{
List<Person> person = conn.Query<dynamic>(sql)
.Select(item => new Person()
{
PersonId = item.person_id,
FirstName = item.first_name,
LastName = item.last_name
}
.ToList();
return person;
}
http://2sharings.com/2018/dapper-orm-manually-map-column-names-with-class-properties-in-csharp-application
Dapper中数据表的字段(列)与实体属性不一致时,如何手动配置它们之间的映射?的更多相关文章
- MySql中数据表增加字段很慢怎么办
正确的做法是这样,对于数据量很大的表,需要添加所有或者修改字段的做法是如下: 1.先创建一张一样的表 create table new_tb like tb_old; 2.修改创建表的字段 alter ...
- c++中数据表如何转成业务实体--map和结构体的相互转换
应用场景:如何把数据库表中的一行转换成一个业务实体结构体,c#和java中都有实体框架,表到实体的转换很方便,c++中缺少这些框架,但是有一些折中的办法去做.其实问题的本质是:map如何转成结构体. ...
- PHP获取mysql数据表的字段名称及详细属性
SHOW DATABASES //列出 MySQL Server 数据库. SHOW TABLES [FROM db_name] //列出数据库数据表. SHOW CREATE TABLES tbl_ ...
- 给MySQL中数据表添加字段
添加一个char字段: mysql> alter table stock add src char(20); Query OK, 3766 rows affected (0.65 sec) Re ...
- mysql中通过sql语句查询指定数据表的字段信息
mysql数据库在安装完成时,自动创建了information_schema.mysql.test这三个数据库.其中,information_schema记录了创建的所有数据库的相关信息,因此可以 ...
- 使用sql查询mysql/oracle/sql server/gp数据库中指定表的字段信息(字段名/字段类型/字段长度/是否是主键/是否为空)
1,根据数据库类型拼接不同URL /** * 根据类型不同拼接连接的URL * @param dbType 1:mysql.2:oracle.3:sql server.4:gp * @param ip ...
- 第二百七十七节,MySQL数据库-数据表、以及列的增删改查
MySQL数据库-数据表.以及列的增删改查 1.创建一个表 CREATE(创建) TABLE(表) ENGINE(引擎) ENGINE=INNODB(引擎)还有很多类引擎,这里只是简单的提一下INNO ...
- MySQL中数据表的基本操纵
本文基于对国家863中部软件孵化器编著的<MySQL从入门到精通>一书的操作实践. 一.创建数据表 数据表属于数据库,在创建数据表之前,应该使用语句 USE 数据库名 指定操作是在那个 ...
- Java对比两个数据库中的表和字段,写个冷门的东西
Java对比两个数据库中的表和字段,写个冷门的东西 转载的 来源网络 目前所在的项目组距离下个版本上线已经很近了,就面临了一个问题:开发人员在开发库上根据需要增加数据表.数据字段.或者变更了字段类型或 ...
随机推荐
- SLAM: Ubuntu14.04_Kylin安装ROS-Indigo
参考连接:ROS-Indigo版在Ubuntu上的安装第一步: 软件源配置 1. 增加下载源(增加ubuntu版的ros数据仓库,即下载源)(通用指令适合任何版本的ros) sudo sh -c 'e ...
- Qt中采用多线程实现Socket编程
Socket通常也称作"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 本文介绍的是Qt中采用多线程Socket编程,由于工作的需要,开始 ...
- python学习笔记之小小购物车
#coding=utf-8 ''' Created on 2015-6-18 @author: 悦文 ''' def goods_list(): shangpin={"} print &qu ...
- VS 2017 统计项目代码总行数
编辑 → 查找和替换 → 在文件中的查找,打开查找窗口 填入正则表达式 ^b*[^:b#/]+.*$ 查找范围选“整个解决方案”,勾选上“使用正则表达式” 如果要限制文件类型,就填上要查找的文件类型 ...
- esp32(M5STACK)在线体验(Ubuntu)
我们往m5stack烧录的固件是可以在线编程的 具体使用方法可以参考 https://github.com/m5stack/M5Cloud/blob/master/README_CN.md ...
- 如何在Loadrunner11中解决HTTP BASIC认证登录报401的问题
在对Carte+kettle的性能测试过程中,通过在loadrunner中用web_set_user("cluster", "cluster","17 ...
- 金蝶WAFII
- 拷贝构造和拷贝赋值、静态成员(static)、成员指针、操作符重载(day06)
十七 拷贝构造和拷贝赋值 浅拷贝和深拷贝 )如果一个类中包含指针形式的成员变量,缺省的拷贝构造函数只是复制了指针变量的本身,而没有复制指针所指向的内容,这种拷贝方式称为浅拷贝. )浅拷贝将导致不同对象 ...
- 51nod1596 搬货物
现在有n个货物,第i个货物的重量是 2wi .每次搬的时候要求货物重量的总和是一个2的幂.问最少要搬几次能把所有的货物搬完. 样例解释: 1,1,2作为一组. 3,3作为一组. Input 单组测试数 ...
- [POI2005]BAN-Bank Notes
[POI2005]BAN-Bank Notes POI真好玩.. 如果没有记录方案的话就是一个简单的二进制或单调队列优化多重背包的问题. 但是非常难受的是要记录方案. 而且空间只给了\(64MB\), ...