using EasyDevCore.Database;
using EasyDevCore.Database.EntityTable;
using EasyDevCore.Common;
using System.Data;
using System.Data.Common;
using System.Dynamic;
using System.Text;
namespace EasyDevCore.Database
{
///
///
///
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;
}
}
}