c# - 是否有在 Dapper 中为 QueryFirstAsync 或 QueryFirstOrDefaultAsync 进行多重映射的选项?

标签 c# sql-server dapper

我正在尝试将对象从 sql 映射到 C# 中的多个对象。在具有 QueryFirstAsync 和 QueryFirstOrDefaultAsync 的情况下如何进行多重映射?

我尝试过类似于 QueryAsync 或 Query 中的过程。

ClassA record = 
await this.dbConnection.QueryFirstAsync<ClassA, ClassB, ClassA>(
sql,                   
(a, b) =>
{
  a.Id = b.Id;                                                                           
  return a;
},
splitOn: "Id",
param: new
{
  memberId
});

我希望构建成功,但它不适用于 QueryFirstAsync 或 QueryFirstOrDefaultAsync。

最佳答案

Current Issue:

您正在尝试将多重映射与小巧的函数一起使用,QueryFirstAsyncQueryFirstOrDefaultAsync , 但它们的重载都不支持 QueryAsync 完成的 Mutli-Mapping ,粘贴 Dapper 代码中的定义:

public static Task<IEnumerable<TReturn>> QueryAsync<TFirst, TSecond, TReturn>(this IDbConnection cnn, 
CommandDefinition command, Func<TFirst, TSecond, TReturn> map, string splitOn = "Id") => 
MultiMapAsync<TFirst, TSecond, DontMap, DontMap, DontMap, DontMap, DontMap, TReturn>(cnn, 
command, map, splitOn);

调用MultiMapAsync , 它利用 SplitOn创建多 map 的值默认为 Id

private static async Task<IEnumerable<TReturn>> MultiMapAsync<TReturn>(this IDbConnection cnn, CommandDefinition command, Type[] types, Func<object[], TReturn> map, string splitOn)
        {
            if (types.Length < 1)
            {
                throw new ArgumentException("you must provide at least one type to deserialize");
            }

            object param = command.Parameters;
            var identity = new Identity(command.CommandText, command.CommandType, cnn, types[0], param?.GetType(), types);
            var info = GetCacheInfo(identity, param, command.AddToCache);
            bool wasClosed = cnn.State == ConnectionState.Closed;
            try
            {
                if (wasClosed) await cnn.TryOpenAsync(command.CancellationToken).ConfigureAwait(false);
                using (var cmd = command.TrySetupAsyncCommand(cnn, info.ParamReader))
                using (var reader = await ExecuteReaderWithFlagsFallbackAsync(cmd, wasClosed, CommandBehavior.SequentialAccess | CommandBehavior.SingleResult, command.CancellationToken).ConfigureAwait(false))
                {
                    var results = MultiMapImpl(null, default(CommandDefinition), types, map, splitOn, reader, identity, true);
                    return command.Buffered ? results.ToList() : results;
                }
            }
            finally
            {
                if (wasClosed) cnn.Close();
            }
        }

Solution:

使用标准QueryAsync ,它有一个重载需要 SplitOn并在最终结果调用FirstorDefault , 因为 Dapper 查询的结果是 IEnumerable<T> , 因此可以调用任何标准的 Linq 扩展方法

关于c# - 是否有在 Dapper 中为 QueryFirstAsync 或 QueryFirstOrDefaultAsync 进行多重映射的选项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57546908/

相关文章:

python - 如何将查询返回中的行号设置为等于列名?

sql-server - 名称与 SQL Server 中的 sys.sysusers 系统 View 冲突

asp.net-mvc-3 - Dapper入门有什么好的示例吗?

c# - 为什么隐式属性名称只能在匿名对象中使用?

c# - wcf新手问题: arrays as properties

c# - 通过委托(delegate)生成接口(interface)实现的工具?

c# - WCF 错误 : 405 Method Not Allowed

sql-server - Azure 查询性能的精确含义

sql - Dapper.net 的奇怪超时问题

c# - Decimal 类型从 In-memory Sqlite 数据库中读取为 double 或 int