[英]How can I make Dapper.NET map unmapped columns to a dictionary?
通过允许一些动态 SQL 进行选择,我的表将包含一些已知的、一些未知的列。 我希望将任何没有匹配属性的列添加到字典中。 基于另一个问题, 当结果集有未映射的列时, 如何使 Dapper.NET 抛出? ,但我不想抛出错误,而是将这些列映射到将在课堂上的字典。
public SqlMapper.IMemberMap GetMember( string columnName ) {
var fallbackMappers = new List<SqlMapper.ITypeMap>();
fallbackMappers.Add( _defaultTypeMap );
var fallbackTypeMapper = new FallbackTypeMapper(fallbackMappers);
var member = fallbackTypeMapper.GetMember(columnName);
if(member == null ) {
throw new Exception();
}
return member;
}
//...
public static async Task<IEnumerable<T>> QueryAsyncOtherProps<T>(
this IDbConnection cnn,
string sql,
object param = null,
IDbTransaction transaction = null,
int? commandTimeout = default,
CommandType? commandType = default
)
where T : BaseSimpleType {
lock ( _lock ) {
if ( TypesThatHaveMapper.ContainsKey( typeof( T ) ) == false ) {
SqlMapper.SetTypeMap( typeof( T ), new NullTypeMapToOtherProperties<T>() );
TypesThatHaveMapper.Add( typeof( T ), null );
}
}
return await cnn.QueryAsync<T>( sql, param, transaction, commandTimeout, commandType );
}
我的 BaseSimpleType 只包含一个名为 OtherProperties 的字典属性,因此只会在具有该字段且名称一致的类型上调用它。 有没有不同的方法来尝试用 Dapper 做到这一点?
我有同样的要求,我想将记录的所有缺失字段映射到IDictionary<string, object> field
。 我已经搜索了足够长的时间,我决定自己实现它。
我创建了一个 Dapper Extension 类。 它只包含一个新方法: .QueryWithExtraFields()
并将 Action<T, Dictionary> 函数作为参数传递,该函数将为每一行调用,该函数将接收类T
实例和每个的IDictionary<string,object>
字段未映射。
使用此Action<>
参数,您可以控制将其设置在您的类中或使用未映射的字段执行其他操作。
预期的 Dapper 返回类
private class ReturnTestClass
{
public int Id { get; set; }
public string Name { get; set; }
public IDictionary<string,object> ExtraFields { get; set; }
}
用法
var results = dbConnection.QueryWithExtraFields<ReturnTestClass>(
sql: "select 1 id, 'Test' as Name, 2 as FieldNumber2, 'other field' as FieldNumber3",
unmappedFieldsAction: (o, unmappedFields) => o.ExtraFields= unmappedFields); //Here is where you place the dictionary inside you type `T` class
DapperExtension.cs 类代码:
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using Dapper;
namespace Dapper {
public static class DapperExtension {
public static IReadOnlyList<T> QueryWithExtraFields<T>(
this DbConnection connection,
string sql,
Action<T, IDictionary<string, object>> unmappedFieldsAction,
object param = null,
DbTransaction transaction = null,
int? commandTimeout = null) where T : new()
{
Dictionary<string, PropertyInfo> propertySetters = typeof(T)
.GetProperties().Where(p => p.CanRead && p.CanWrite)
.ToDictionary(p => p.Name.ToLowerInvariant(), p => p);
return connection.Query(sql: sql, param: param, transaction: transaction, commandTimeout: commandTimeout.GetValueOrDefault(_defaultCommandTimeout))
.Select(row =>
{
IDictionary<string, object> rowDict = (IDictionary<string, object>) row;
T instance = new T();
rowDict.Where(o => propertySetters.ContainsKey(o.Key.ToLowerInvariant()))
.ToList().ForEach(o => propertySetters[o.Key.ToLowerInvariant()].SetValue(instance, o.Value));
unmappedFieldsAction(instance,
rowDict.Where(o => !propertySetters.ContainsKey(o.Key.ToLowerInvariant()))
.ToDictionary(k => k.Key,
v => v.Value));
return instance;
})
.ToArray();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.