/// <summary> /// 查询并根据结果创建目标类型的实例。 /// SQL命中的记录必须为1行,否则抛出异常。 /// </summary> /// <typeparam name="T">查询的目标类型。</typeparam> /// <param name="client"><see cref="IDbClient"/>的实例。</param> /// <param name="sql">SQL语句。</param> /// <param name="param">记录SQL参数的对象。</param> /// <param name="commandType">命令的类型。</param> /// <param name="timeout">命令的超时时间,单位毫秒。0为不指定。</param> /// <returns>目标类型的实例。</returns> /// <exception cref="IncorrectResultSizeException">当SQL命中的记录行数不为 1。</exception> public static T ForceGet <T>(this IDbClient client, string sql, object param = null, CommandType commandType = CommandType.Text, int timeout = 0) { var paramType = param?.GetType(); var id = new CommandIdentity(client.ConnectionString, sql, commandType, paramType, typeof(T)); var cache = CommandCache.Get(id); if (cache != null) { return(client.ForceGet((IMapper <T>)cache.Mapper, cache.Sql, cache.Params(client, param), commandType, timeout)); } cache = CreateCacheItem(sql, commandType, param); var dbParam = cache.Params(client, param); var rows = client.Rows(sql, dbParam, commandType, timeout); IDataRecord row; int rowCount; if (!DbClientHelper.TryReadUniqueRow(rows, out row, out rowCount)) { throw new IncorrectResultSizeException(sql, CommandType.Text, dbParam, 1, rowCount); } var mapper = MapperParser.Parse <T>(row); cache.Mapper = mapper; CommandCache.Set(id, cache); var res = mapper.MapRow(row, 1); return(res); }
/// <summary> /// 查询并根据结果创建目标类型的实例。 /// SQL命中的记录必须为1行,否则抛出异常。 /// 这是一个异步操作。 /// </summary> /// <typeparam name="T">查询的目标类型。</typeparam> /// <param name="client"><see cref="IDbClient"/>的实例。</param> /// <param name="sql">SQL语句。</param> /// <param name="param">参数表。</param> /// <returns>目标类型的实例。</returns> /// <exception cref="IncorrectResultSizeException">当SQL命中的记录行数不为 1。</exception> public static async Task <T> IxForceGetAsync <T>(this IDbClient client, string sql, params object[] param) { var identity = new CommandIdentity(client.ConnectionString, sql, null, null, typeof(T)); var cache = CommandCache.Get(identity); if (cache != null) { return(await IxForceGetAsync(client, (IMapper <T>) cache.Mapper, sql, param)); } var dbParam = GenerateParameters(client, param).ToList(); var rows = await client.RowsAsync(sql, dbParam); IDataRecord row; int rowCount; if (!DbClientHelper.TryReadUniqueRow(rows, out row, out rowCount)) { throw new IncorrectResultSizeException(sql, CommandType.Text, dbParam, 1, rowCount); } var mapper = MapperParser.Parse <T>(row); CommandCache.Set(identity, new CommandCacheItem { Mapper = mapper }); var res = mapper.MapRow(row, 1); return(res); }
/// <summary> /// 使用<see cref="IMapper{T}"/>查询指定对象。 /// SQL命中的记录必须为1行,否则抛出异常。 /// 这是一个异步操作。 /// </summary> /// <typeparam name="T">查询的目标类型。</typeparam> /// <param name="mapper"><see cref="IMapper{T}"/>的实例。</param> /// <param name="sql">查询SQL。</param> /// <param name="parameters">参数序列。空序列或null表示没有参数。</param> /// <param name="commandType">命令的类型。</param> /// <param name="timeout">命令的超时时间,单位毫秒。0表示不指定,此时套用默认的超时设置。</param> /// <returns>目标类型的实例。</returns> /// <exception cref="IncorrectResultSizeException">当SQL命中的记录行数不为 1。</exception> public virtual async Task <T> ForceGetAsync <T>(IMapper <T> mapper, string sql, IEnumerable <DbParameter> parameters = null, CommandType commandType = CommandType.Text, int timeout = 0) { if (!AsyncEnabled) { return(ForceGet(mapper, sql, parameters, commandType, timeout)); } DbConnection connection = null; IDataReader reader = null; DbCommand cmd = null; try { connection = await CreateAndOpenConnectionAsync(); cmd = CreateCommand(sql, connection, parameters, commandType, timeout); reader = await cmd.ExecuteReaderAsync(); int rowCount; T result; if (DbClientHelper.TryMapUniqueRow(reader, mapper, out result, out rowCount)) { return(result); } throw new IncorrectResultSizeException(sql, CommandType.Text, parameters, 1, rowCount); } catch (Exception ex) { throw new SqlExecutingException(sql, commandType, parameters, ex); } finally { cmd?.Parameters.Clear(); if (reader != null && !reader.IsClosed) { reader.Close(); } if (connection != null) { CloseConnection(connection); } } }
/// <summary> /// 使用<see cref="IMapper{T}"/>查询指定对象。 /// SQL命中的记录必须为1行,否则抛出异常。 /// </summary> /// <typeparam name="T">查询的目标类型。</typeparam> /// <param name="mapper"><see cref="IMapper{T}"/>的实例。</param> /// <param name="sql">查询SQL。</param> /// <param name="parameters">参数序列。空序列或null表示没有参数。</param> /// <param name="commandType">命令的类型。</param> /// <param name="timeout">命令的超时时间,单位毫秒。0表示不指定,此时套用默认的超时设置。</param> /// <returns>目标类型的实例。</returns> /// <exception cref="IncorrectResultSizeException">当SQL命中的记录行数不为 1。</exception> public virtual T ForceGet <T>(IMapper <T> mapper, string sql, IEnumerable <DbParameter> parameters = null, CommandType commandType = CommandType.Text, int timeout = 0) { ArgAssert.NotNullOrEmpty(sql, nameof(sql)); ArgAssert.NotNull(mapper, nameof(mapper)); DbConnection connection = null; IDataReader reader = null; DbCommand cmd = null; try { connection = CreateAndOpenConnection(); cmd = CreateCommand(sql, connection, parameters, commandType, timeout); reader = cmd.ExecuteReader(); int rowCount; T result; if (DbClientHelper.TryMapUniqueRow(reader, mapper, out result, out rowCount)) { return(result); } throw new IncorrectResultSizeException(sql, CommandType.Text, parameters, 1, rowCount); } catch (Exception ex) { throw new SqlExecutingException(sql, commandType, parameters, ex); } finally { cmd?.Parameters.Clear(); if (reader != null && !reader.IsClosed) { reader.Close(); } if (connection != null) { CloseConnection(connection); } } }