繁体   English   中英

如何让 Dapper.NET 将未映射的列映射到字典?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM