背景:

在.net core 2.0 Asp.mvc 项目中使用dapper 框架

一、

数据库字段名和model属性名一一对应时,直接只用dapper方法是没有问题的,比如:

//实体类

public class Books

{

[Dapper.Key]

public int Id { get; set; }

public string Name { get; set; }

public string Author { get; set; }

}

数据库:book表

直接使用dapper对象的方法,传入model对象:

//默认映射

string sql = $"SELECT * FROM book ";

database.QueryListSQL(sql).ToList();

//直接传入实体对象

bool result = await database.CreateAsync(book) > 0;

好处是不需要在sql语句中将字段一个个写出来,直接使用table-model映射关系,非常便利!

二、

但是,也会有字段名和属性名不对应的情况,比如:

public class ReadBooks

{

public DateTime CreateTime { get; set; }

}

那么,在C#程序中,使用Dapper做查询时,如何配置数据表字段(列)和实体类属性之间的映射呢?

method 1:

查询时,可以在select语句中使用AS别名,别名与model对应:

var sql = @"select create_time AS CreateTime from book";

database.Single(sql);

插入/更新时,依然需要 列名-值 :

//dapper插入语句,表名和字段名

database.InsertSQL($@"book",new DataColumn("Author", book.Author),

new DataColumn("Name", book.Name),

new DataColumn("create_time", DateTime.Now)

);

method 2:

查询时,还可以使用Linq:

//搭配动态类型dynamic使用

List book= database.Query(sql)

.Select(item => new Books()

{

CreatTime= creat_time

}

.ToList();

method 3:

如果有很多数据库表字段和model属性不对应的话,我们每次都使用别名和linq就有些麻烦,如果能像EF那样,在model属性上加一个Attribute来表明字段和属性映射关系就好了,EF:

class School

{

/*

若属性名和数据库字段不一致(不区分大小写)则查询不出数据,如果使用EF则可以通过Column特性

建立属性和数据表字段之间的映射关系,Dapper则不行

*/

//[Column("Name")]

public string Title { set; get; }

public string Address { set; get; }

}

Dapper虽然有colmun的特性,但是并不能完成字段-属性映射;

我们需要手动拓展一个colmun特性出来,以完成如EF的绑定。

1,添加一个类ColumnAttributeTypeMapper,用于字段-属性映射:

using Dapper;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Reflection;

namespace 命名空间

{

///

/// Uses the Name value of the 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.

///

/// The type of the object that this association between the mapper applies to.

public class ColumnAttributeTypeMapper : FallbackTypeMapper

{

public ColumnAttributeTypeMapper()

: base(new SqlMapper.ITypeMap[]

{

new CustomPropertyTypeMap(

typeof(T),

(type, columnName) =>

type.GetProperties().FirstOrDefault(prop =>

prop.GetCustomAttributes(false)

.OfType()

.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 _mappers;

public FallbackTypeMapper(IEnumerable 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);

}

}

}

2,再添加一个类ColumnMapper,用于添加映射关系:

using Dapper;

using 引入需要的.Models;

namespace 项目命名空间

{

public class ColumnMapper

{

public static void SetMapper()

{

//数据库字段名和c#属性名不一致,手动添加映射关系

SqlMapper.SetTypeMap(typeof(Books), new ColumnAttributeTypeMapper());

//每个需要用到[colmun(Name="")]特性的model,都要在这里添加映射

}

}

}

3,在starup.cs类的中方法注册:

public void ConfigureServices(IServiceCollection services)

{

services.AddMvc();

services.AddSession();

//调用前面的静态方法,将映射关系注册

ColumnMapper.SetMapper();

}

4,最后就可以在model的属性名上添加特性来映射到数据库字段名了:

using 引入新加的类.Helper;

public class Books

{

[Column(Name = "create_time")]

public DateTime CreateTime { get; set; }

}

这样我们就可以在所有的不与数据库对应的model中,方便的添加映射关系了!

————————————————

版权声明:本文为CSDN博主「Zdelta」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/Zdelta/java/article/details/87636491

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐