using EasyDev.Database; using EasyDev.Database.EntityTable; using EasyDevCore.Common; using System.Data; using System.Data.Common; using System.Dynamic; using System.Text; namespace EasyDevCore.Database.EntityFrameworkCore { /// /// /// public static class DbDataReaderExtensions { /// /// Gets the value. /// /// /// The reader. /// Name of the field. /// The value if null. /// public static T GetValue(this DbDataReader reader, string fieldName, T valueIfNull) { int colIndex = reader.GetOrdinal(fieldName); object value = reader.GetValue(colIndex); if (value == null) return valueIfNull; Type columnType = reader.GetFieldType(colIndex); if (typeof(T) == columnType) { return (T)value; } else { return (T)Convert.ChangeType(value, columnType); } } /// /// Gets the row. /// /// The reader. /// public static dynamic GetRow(this DbDataReader reader) { IDictionary expandoObject = new ExpandoObject() as IDictionary; var fieldCount = reader.FieldCount; for (var i = 0; i < fieldCount; i++) expandoObject.Add(reader.GetName(i), reader.IsDBNull(i) ? null : reader[i]); return expandoObject; } /// /// Gets the row asynchronous. /// /// The reader. /// The cancellation token. /// public static async Task GetRowAsync(this DbDataReader reader, CancellationToken cancellationToken) { var expandoObject = new ExpandoObject() as IDictionary; for (var i = 0; i < reader.FieldCount; i++) { object value = await reader.IsDBNullAsync(i, cancellationToken).ConfigureAwait(false) ? null : reader.GetValue(i); expandoObject.Add(reader.GetName(i), value); } return expandoObject; } /// /// Fetches to json. /// /// The reader. /// if set to true [indent format]. /// public static string FetchToJson(this DbDataReader reader, bool indentFormat = false) { if (reader.IsClosed) return null; var JSONString = new StringBuilder(); if (indentFormat) { JSONString.AppendLine("["); while (reader.Read()) { JSONString.AppendLine("{"); for (int i = 0; i < reader.FieldCount; i++) { string value = "\"" + reader.GetName(i) + "\":" + (reader.IsDBNull(i) ? "null" : "\"" + System.Web.HttpUtility.JavaScriptStringEncode(reader[i].StringFrom()) + "\"" ); if (i < reader.FieldCount - 1) { value += ","; } JSONString.AppendLine(value); } JSONString.AppendLine("}"); } JSONString.AppendLine("]"); } else { JSONString.Append("["); while (reader.Read()) { JSONString.Append("{"); for (int i = 0; i < reader.FieldCount; i++) { string value = "\"" + reader.GetName(i) + "\":" + (reader.IsDBNull(i) ? "null" : "\"" + System.Web.HttpUtility.JavaScriptStringEncode(reader[i].StringFrom()) + "\"" ); if (i < reader.FieldCount - 1) { value += ","; } JSONString.Append(value); } JSONString.Append("}"); } JSONString.Append("]"); } return JSONString.ToString(); } /// /// Fetches to json asynchronous. /// /// The reader. /// if set to true [indent format]. /// The cancellation token. /// public static async Task FetchToJsonAsync(this DbDataReader reader, bool indentFormat = false, CancellationToken cancellationToken = default) { if (reader.IsClosed) return null; var JSONString = new StringBuilder(); if (indentFormat) { JSONString.AppendLine("["); while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) { JSONString.AppendLine("{"); for (int i = 0; i < reader.FieldCount; i++) { string value = "\"" + reader.GetName(i) + "\":" + (await reader.IsDBNullAsync(i, cancellationToken).ConfigureAwait(false) ? "null" : "\"" + System.Web.HttpUtility.JavaScriptStringEncode(reader[i].StringFrom()) + "\""); if (i < reader.FieldCount - 1) { value += ","; } JSONString.AppendLine(value); } JSONString.AppendLine("}"); } JSONString.AppendLine("]"); } else { JSONString.Append("["); while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) { JSONString.Append("{"); for (int i = 0; i < reader.FieldCount; i++) { string value = "\"" + reader.GetName(i) + "\":" + (await reader.IsDBNullAsync(i, cancellationToken).ConfigureAwait(false) ? "null" : "\"" + System.Web.HttpUtility.JavaScriptStringEncode(reader[i].StringFrom()) + "\""); if (i < reader.FieldCount - 1) { value += ","; } JSONString.Append(value); } JSONString.Append("}"); } JSONString.Append("]"); } return JSONString.ToString(); } /// /// Fetches to list. /// /// The reader. /// public static IList FetchToDynamic(this DbDataReader reader) { if (reader.IsClosed) return null; List list = new(); while (reader.Read()) { list.Add(reader.GetRow()); } return list; } /// /// Fetches to dynamic asynchronous. /// /// The reader. /// The cancellation token. /// public static async Task> FetchToDynamicAsync(this DbDataReader reader, CancellationToken cancellationToken = default) { if (reader.IsClosed) return null; List list = new(); DataRecordDynamic wrapper = new(reader); while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) { list.Add(await reader.GetRowAsync(cancellationToken).ConfigureAwait(false)); } bool hasNextResult = await reader.NextResultAsync(cancellationToken).ConfigureAwait(false); if (!hasNextResult) await reader.CloseAsync().ConfigureAwait(false); return list; } /// /// Fetches the fill list internal. /// /// /// The reader. /// The list. /// private static IList FetchFillListInternal(this DbDataReader reader, IList list) where T : class, new() { if (reader.IsClosed) return null; var mapper = new DbDataReaderMapper(reader); mapper.Map(row => list.Add(row)); bool hasNextResult = reader.NextResult(); if (!hasNextResult) reader.Close(); return list; } /// /// Fetches the fill list internal asynchronous. /// /// /// The reader. /// The list. /// The cancellation token. /// private async static Task> FetchFillListInternalAsync(this DbDataReader reader, IList list, CancellationToken cancellationToken = default) where T : class, new() { if (reader.IsClosed) return null; var mapper = new DbDataReaderMapper(reader); await mapper.MapAsync(row => list.Add(row), cancellationToken).ConfigureAwait(false); bool hasNextResult = await reader.NextResultAsync(cancellationToken).ConfigureAwait(false); if (!hasNextResult) await reader.CloseAsync().ConfigureAwait(false); return list; } /// /// Fetches the fill list. /// /// /// The reader. /// The list. /// public static int FetchFillList(this DbDataReader reader, IList list) where T : class, new() { int rowsCount = list.Count; return reader.FetchFillListInternal(list).Count - rowsCount; } /// /// Fetches the fill list asynchronous. /// /// /// The reader. /// The list. /// The cancellation token. /// public static async Task FetchFillListAsync(this DbDataReader reader, IList list, CancellationToken cancellationToken = default) where T : class, new() { int rowsCount = list.Count; return (await reader.FetchFillListInternalAsync(list, cancellationToken).ConfigureAwait(false)).Count - rowsCount; } /// /// Fetches to list. /// /// The type of the result. /// The reader. /// The selector. /// public static IList FetchToList(this DbDataReader reader, Func selector) { if (reader.IsClosed) return null; List list = new(); DataRecordDynamic wrapper = new(reader); while (reader.Read()) { var item = selector(wrapper); list.Add(item); } bool hasNextResult = reader.NextResult(); if (!hasNextResult) reader.Close(); return list; } /// /// Fetches to list asynchronous. /// /// The type of the result. /// The reader. /// The selector. /// The cancellation token. /// public static async Task> FetchToListAsync(this DbDataReader reader, Func selector, CancellationToken cancellationToken = default) { if (reader.IsClosed) return null; List list = new(); DataRecordDynamic wrapper = new(reader); while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false)) { var item = selector(wrapper); list.Add(item); } bool hasNextResult = await reader.NextResultAsync(cancellationToken).ConfigureAwait(false); if (!hasNextResult) await reader.CloseAsync().ConfigureAwait(false); return list; } /// /// Fetches to list. /// /// /// The reader. /// The list. /// public static IList FetchToList(this DbDataReader reader, IList list = null) where T : class, new() { if (reader.IsClosed) return list; IList listNew = list ?? new List(); listNew.Clear(); return reader.FetchFillListInternal(listNew); } /// /// Fetches to list asynchronous. /// /// /// The reader. /// The list. /// The cancellation token. /// public static async Task> FetchToListAsync(this DbDataReader reader, IList list = null, CancellationToken cancellationToken = default) where T : class, new() { if (reader.IsClosed) return list; IList listNew = list ?? new List(); listNew.Clear(); return await reader.FetchFillListInternalAsync(listNew, cancellationToken).ConfigureAwait(false); } /// /// Fetches the fill data set. /// /// The reader. /// The data set. public static int FetchFillDataSet(this DbDataReader reader, DataSet dataSet) { if (dataSet.Tables.Count == 0) return 0; var totalRows = dataSet.Tables.Cast().Sum(tb => tb.Rows.Count); int i = 0; do { dataSet.Tables[i].Load(reader); i++; } while (dataSet.Tables.Count > i && !reader.IsClosed); return dataSet.Tables.Cast().Sum(tb => tb.Rows.Count) - totalRows; } /// /// Fetches the fill data set asynchronous. /// /// The reader. /// The data set. /// The cancellation token. /// public static async Task FetchFillDataSetAsync(this DbDataReader reader, DataSet dataSet, CancellationToken cancellationToken = default) { if (dataSet.Tables.Count == 0) return 0; var totalRows = dataSet.Tables.Cast().Sum(tb => tb.Rows.Count); int i = 0; do { await dataSet.Tables[i].LoadAsync(reader, cancellationToken).ConfigureAwait(false); } while (dataSet.Tables.Count > i && !reader.IsClosed); return dataSet.Tables.Cast().Sum(tb => tb.Rows.Count) - totalRows; } // /// /// Fetches to data set. /// /// The reader. /// The data set. /// The parameters. /// public static DataSet FetchToDataSet(this DbDataReader reader, DataSet dataSet = null, EasyDbParameterCollection parameters = null) { if (dataSet != null) dataSet.Clear(); DataSet newDataSet = dataSet ?? new DataSet(); do { newDataSet.Tables.Add().Load(reader, LoadOption.Upsert); if (parameters != null) { var result = ParameterUtils.GatherOutputParameters(0, parameters); foreach (var item in result) { newDataSet.ExtendedProperties[item.Key] = item.Value; } } } while (!reader.IsClosed); return newDataSet; } /// /// Fetches to data set asynchronous. /// /// The reader. /// The entity set. /// The cancellation token. /// public static async Task FetchToDataSetAsync(this DbDataReader reader, DataSet DataSet = null, CancellationToken cancellationToken = default) { if (DataSet != null) DataSet.Clear(); DataSet newDataSet = DataSet ?? new DataSet(); do { await newDataSet.Tables.Add().LoadAsync(reader, cancellationToken).ConfigureAwait(false); } while (!reader.IsClosed); return newDataSet; } /// /// Fetches to table. /// /// The reader. /// The table. /// public static int FetchFillTable(this DbDataReader reader, DataTable table) { int totalRows = table.Rows.Count; table.Load(reader); return table.Rows.Count - totalRows; } /// /// Fetches to table. /// /// The reader. /// The table. /// The cancellation token. /// public static async Task FetchFillTableAsync(this DbDataReader reader, DataTable table, CancellationToken cancellationToken = default) { if (reader.IsClosed) return 0; int totalRows = table.Rows.Count; await table.LoadAsync(reader); return table.Rows.Count - totalRows; } /// /// Fetches to table. /// /// The reader. /// The table. /// public static DataTable FetchToTable(this DbDataReader reader, DataTable table = null) { if (table != null) table.Clear(); DataTable newTable = table ?? new DataTable(); newTable.Load(reader); return newTable; } /// /// Fetches to table asynchronous. /// /// The reader. /// The table. /// The cancellation token. /// public static async Task FetchToTableAsync(this DbDataReader reader, DataTable table = null, CancellationToken cancellationToken = default) { if (table != null) table.Clear(); DataTable newTable = table ?? new DataTable(); await newTable.LoadAsync(reader, cancellationToken).ConfigureAwait(false); return newTable; } } }