diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs
index 3915a0c..b4d33f3 100644
--- a/AmalgamationTool/DynamORM.Amalgamation.cs
+++ b/AmalgamationTool/DynamORM.Amalgamation.cs
@@ -96,6 +96,95 @@ namespace DynamORM
#region Helpers
+ /// Create data reader from dynamic enumerable.
+ /// List of objects.
+ /// Instance of containing objects data.
+ public static DynamicCachedReader FromDynamicEnumerable(IEnumerable objects)
+ {
+ var first = (objects as IEnumerable).FirstOrDefault();
+
+ if (first == null)
+ return null;
+
+ var firstDict = first as IDictionary;
+ var r = new DynamicCachedReader();
+ r.Init(firstDict.Keys.Count);
+
+ for (int i = 0; i < firstDict.Keys.Count; i++)
+ r._types.Add(null);
+
+ foreach (dynamic elem in (objects as IEnumerable))
+ {
+ int c = 0;
+ var dict = elem as IDictionary;
+
+ foreach (var k in firstDict.Keys)
+ {
+ object val = dict[k];
+
+ r._cache.Add(val);
+
+ if (r._types[c] == null && val != null)
+ r._types[c] = val.GetType();
+
+ c++;
+ }
+
+ r._rows++;
+ }
+
+ for (int i = 0; i < firstDict.Keys.Count; i++)
+ if (r._types[i] == null)
+ r._types[i] = typeof(string);
+
+ r._schema = new DataTable("DYNAMIC");
+ r._schema.Columns.Add(new DataColumn("ColumnName", typeof(string)));
+ r._schema.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("ColumnSize", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("NumericPrecision", typeof(short)));
+ r._schema.Columns.Add(new DataColumn("NumericScale", typeof(short)));
+ r._schema.Columns.Add(new DataColumn("DataType", typeof(Type)));
+ r._schema.Columns.Add(new DataColumn("ProviderType", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("NativeType", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("AllowDBNull", typeof(bool)));
+ r._schema.Columns.Add(new DataColumn("IsUnique", typeof(bool)));
+ r._schema.Columns.Add(new DataColumn("IsKey", typeof(bool)));
+ r._schema.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool)));
+
+ int ordinal = 0;
+ DataRow dr = null;
+
+ foreach (var column in firstDict.Keys)
+ {
+ dr = r._schema.NewRow();
+
+ dr[0] = column;
+ dr[1] = ordinal;
+ dr[2] = 0;
+ dr[3] = 0;
+ dr[4] = 0;
+ dr[5] = r._types[ordinal];
+ dr[6] = r._types[ordinal].ToDbType();
+ dr[7] = r._types[ordinal].ToDbType();
+ dr[8] = true;
+ dr[9] = false;
+ dr[10] = false;
+ dr[11] = false;
+
+ r._schema.Rows.Add(dr);
+
+ r._names.Add(dr[0].ToString());
+ r._ordinals.Add(dr[0].ToString().ToUpper(), ordinal++);
+ r._types.Add((Type)dr[5]);
+
+ dr.AcceptChanges();
+ }
+
+ dr.AcceptChanges();
+
+ return r;
+ }
+
/// Create data reader from enumerable.
/// Type of enumerated objects.
/// List of objects.
@@ -2773,6 +2862,44 @@ namespace DynamORM
#endregion Query
+ #region CachedQuery
+
+ /// Enumerate the reader and yield the result.
+ /// SQL query containing numbered parameters in format provided by
+ /// methods. Also names should be formatted with
+ /// method.
+ /// Arguments (parameters).
+ /// Enumerator of objects expanded from query.
+ public virtual DynamicCachedReader CachedQuery(string sql, params object[] args)
+ {
+ using (IDbConnection con = Open())
+ using (IDbCommand cmd = con.CreateCommand())
+ {
+ using (IDataReader rdr = cmd
+ .SetCommand(sql)
+ .AddParameters(this, args)
+ .ExecuteReader())
+ return new DynamicCachedReader(rdr);
+ }
+ }
+
+ /// Enumerate the reader and yield the result.
+ /// Command builder.
+ /// Enumerator of objects expanded from query.
+ public virtual DynamicCachedReader CachedQuery(IDynamicQueryBuilder builder)
+ {
+ using (IDbConnection con = Open())
+ using (IDbCommand cmd = con.CreateCommand())
+ {
+ using (IDataReader rdr = cmd
+ .SetCommand(builder)
+ .ExecuteReader())
+ return new DynamicCachedReader(rdr);
+ }
+ }
+
+ #endregion Query
+
#region Schema
/// Builds query cache if necessary and returns it.
@@ -10855,6 +10982,45 @@ namespace DynamORM
}
}
+ /// Extensions for data reader handling.
+ public static class DataReaderExtensions
+ {
+ /// Gets the data table from data reader.
+ /// The data reader.
+ /// The name to give the table. If tableName is null or an empty string, a default name is given when added to the System.Data.DataTableCollection.
+ /// The namespace for the XML representation of the data stored in the DataTable.
+ ///
+ public static DataTable GetDataTableFromDataReader(this IDataReader r, string name = null, string nameSpace = null)
+ {
+ DataTable schemaTable = r.GetSchemaTable();
+ DataTable resultTable = new DataTable(name, nameSpace);
+
+ foreach (DataRow col in schemaTable.Rows)
+ {
+ dynamic c = col.RowToDynamicUpper();
+
+ DataColumn dataColumn = new DataColumn();
+ dataColumn.ColumnName = c.COLUMNNAME;
+ dataColumn.DataType = (Type)c.DATATYPE;
+ dataColumn.ReadOnly = true;
+ dataColumn.Unique = c.ISUNIQUE;
+
+ resultTable.Columns.Add(dataColumn);
+ }
+
+ while (r.Read())
+ {
+ DataRow row = resultTable.NewRow();
+ for (int i = 0; i < resultTable.Columns.Count - 1; i++)
+ row[i] = r[i];
+
+ resultTable.Rows.Add(row);
+ }
+
+ return resultTable;
+ }
+ }
+
/// Framework detection and specific implementations.
public static class FrameworkTools
{
diff --git a/DynamORM/DynamORM.csproj b/DynamORM/DynamORM.csproj
index 0aab04a..189cbda 100644
--- a/DynamORM/DynamORM.csproj
+++ b/DynamORM/DynamORM.csproj
@@ -3,10 +3,10 @@
netstandard2.0;net472;net5.0;net6.0
Dynamic Object-Relational Mapping library.
- Copyright © RUSSEK Software 2012-2022
+ Copyright © RUSSEK Software 2012-2023
RUSSEK Software
Grzegorz Russek
- 1.2.4
+ 1.2.5
https://svn.dr4cul4.pl/svn/DynamORM/
https://dr4cul4.pl
DynamORM
diff --git a/DynamORM/DynamicCachedReader.cs b/DynamORM/DynamicCachedReader.cs
index 3099f68..d39bbbb 100644
--- a/DynamORM/DynamicCachedReader.cs
+++ b/DynamORM/DynamicCachedReader.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.IO;
+using System.Linq;
using DynamORM.Helpers;
using DynamORM.Mapper;
@@ -43,6 +44,95 @@ namespace DynamORM
#region Helpers
+ /// Create data reader from dynamic enumerable.
+ /// List of objects.
+ /// Instance of containing objects data.
+ public static DynamicCachedReader FromDynamicEnumerable(IEnumerable objects)
+ {
+ var first = (objects as IEnumerable).FirstOrDefault();
+
+ if (first == null)
+ return null;
+
+ var firstDict = first as IDictionary;
+ var r = new DynamicCachedReader();
+ r.Init(firstDict.Keys.Count);
+
+ for (int i = 0; i < firstDict.Keys.Count; i++)
+ r._types.Add(null);
+
+ foreach (dynamic elem in (objects as IEnumerable))
+ {
+ int c = 0;
+ var dict = elem as IDictionary;
+
+ foreach (var k in firstDict.Keys)
+ {
+ object val = dict[k];
+
+ r._cache.Add(val);
+
+ if (r._types[c] == null && val != null)
+ r._types[c] = val.GetType();
+
+ c++;
+ }
+
+ r._rows++;
+ }
+
+ for (int i = 0; i < firstDict.Keys.Count; i++)
+ if (r._types[i] == null)
+ r._types[i] = typeof(string);
+
+ r._schema = new DataTable("DYNAMIC");
+ r._schema.Columns.Add(new DataColumn("ColumnName", typeof(string)));
+ r._schema.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("ColumnSize", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("NumericPrecision", typeof(short)));
+ r._schema.Columns.Add(new DataColumn("NumericScale", typeof(short)));
+ r._schema.Columns.Add(new DataColumn("DataType", typeof(Type)));
+ r._schema.Columns.Add(new DataColumn("ProviderType", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("NativeType", typeof(int)));
+ r._schema.Columns.Add(new DataColumn("AllowDBNull", typeof(bool)));
+ r._schema.Columns.Add(new DataColumn("IsUnique", typeof(bool)));
+ r._schema.Columns.Add(new DataColumn("IsKey", typeof(bool)));
+ r._schema.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool)));
+
+ int ordinal = 0;
+ DataRow dr = null;
+
+ foreach (var column in firstDict.Keys)
+ {
+ dr = r._schema.NewRow();
+
+ dr[0] = column;
+ dr[1] = ordinal;
+ dr[2] = 0;
+ dr[3] = 0;
+ dr[4] = 0;
+ dr[5] = r._types[ordinal];
+ dr[6] = r._types[ordinal].ToDbType();
+ dr[7] = r._types[ordinal].ToDbType();
+ dr[8] = true;
+ dr[9] = false;
+ dr[10] = false;
+ dr[11] = false;
+
+ r._schema.Rows.Add(dr);
+
+ r._names.Add(dr[0].ToString());
+ r._ordinals.Add(dr[0].ToString().ToUpper(), ordinal++);
+ r._types.Add((Type)dr[5]);
+
+ dr.AcceptChanges();
+ }
+
+ dr.AcceptChanges();
+
+ return r;
+ }
+
/// Create data reader from enumerable.
/// Type of enumerated objects.
/// List of objects.
diff --git a/DynamORM/DynamicDatabase.cs b/DynamORM/DynamicDatabase.cs
index 010fb85..639bc92 100644
--- a/DynamORM/DynamicDatabase.cs
+++ b/DynamORM/DynamicDatabase.cs
@@ -1310,6 +1310,44 @@ namespace DynamORM
#endregion Query
+ #region CachedQuery
+
+ /// Enumerate the reader and yield the result.
+ /// SQL query containing numbered parameters in format provided by
+ /// methods. Also names should be formatted with
+ /// method.
+ /// Arguments (parameters).
+ /// Enumerator of objects expanded from query.
+ public virtual DynamicCachedReader CachedQuery(string sql, params object[] args)
+ {
+ using (IDbConnection con = Open())
+ using (IDbCommand cmd = con.CreateCommand())
+ {
+ using (IDataReader rdr = cmd
+ .SetCommand(sql)
+ .AddParameters(this, args)
+ .ExecuteReader())
+ return new DynamicCachedReader(rdr);
+ }
+ }
+
+ /// Enumerate the reader and yield the result.
+ /// Command builder.
+ /// Enumerator of objects expanded from query.
+ public virtual DynamicCachedReader CachedQuery(IDynamicQueryBuilder builder)
+ {
+ using (IDbConnection con = Open())
+ using (IDbCommand cmd = con.CreateCommand())
+ {
+ using (IDataReader rdr = cmd
+ .SetCommand(builder)
+ .ExecuteReader())
+ return new DynamicCachedReader(rdr);
+ }
+ }
+
+ #endregion Query
+
#region Schema
/// Builds query cache if necessary and returns it.
diff --git a/DynamORM/Helpers/DataReaderExtensions.cs b/DynamORM/Helpers/DataReaderExtensions.cs
new file mode 100644
index 0000000..dd8bd95
--- /dev/null
+++ b/DynamORM/Helpers/DataReaderExtensions.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Data;
+
+namespace DynamORM.Helpers
+{
+ /// Extensions for data reader handling.
+ public static class DataReaderExtensions
+ {
+ /// Gets the data table from data reader.
+ /// The data reader.
+ /// The name to give the table. If tableName is null or an empty string, a default name is given when added to the System.Data.DataTableCollection.
+ /// The namespace for the XML representation of the data stored in the DataTable.
+ ///
+ public static DataTable GetDataTableFromDataReader(this IDataReader r, string name = null, string nameSpace = null)
+ {
+ DataTable schemaTable = r.GetSchemaTable();
+ DataTable resultTable = new DataTable(name, nameSpace);
+
+ foreach (DataRow col in schemaTable.Rows)
+ {
+ dynamic c = col.RowToDynamicUpper();
+
+ DataColumn dataColumn = new DataColumn();
+ dataColumn.ColumnName = c.COLUMNNAME;
+ dataColumn.DataType = (Type)c.DATATYPE;
+ dataColumn.ReadOnly = true;
+ dataColumn.Unique = c.ISUNIQUE;
+
+ resultTable.Columns.Add(dataColumn);
+ }
+
+ while (r.Read())
+ {
+ DataRow row = resultTable.NewRow();
+ for (int i = 0; i < resultTable.Columns.Count - 1; i++)
+ row[i] = r[i];
+
+ resultTable.Rows.Add(row);
+ }
+
+ return resultTable;
+ }
+ }
+}