From 4847af02bdf954faf25e631b37f02b12c31f8dcf Mon Sep 17 00:00:00 2001 From: Grzegorz Russek Date: Tue, 13 Jan 2026 16:37:20 +0100 Subject: [PATCH] Added new cached reader to single file version --- AmalgamationTool/DynamORM.Amalgamation.cs | 363 +++++++++++++--------- 1 file changed, 210 insertions(+), 153 deletions(-) diff --git a/AmalgamationTool/DynamORM.Amalgamation.cs b/AmalgamationTool/DynamORM.Amalgamation.cs index 2e47ddb..5a7d570 100644 --- a/AmalgamationTool/DynamORM.Amalgamation.cs +++ b/AmalgamationTool/DynamORM.Amalgamation.cs @@ -67,16 +67,23 @@ namespace DynamORM { #region Constructor and Data - private DataTable _schema; - private int _fields; - private int _rows; - private int _position; - private int _cachePos; + private class Data + { + internal DataTable _schema; + internal int _fields; + internal int _rows; + internal int _rowsAffected; + internal int _position = -1; + internal int _cachePos = -1; - private IList _names; - private IDictionary _ordinals; - private IList _types; - private IList _cache; + internal IList _names; + internal IDictionary _ordinals; + internal IList _types; + internal IList _cache; + } + + private List _data = new List(); + private int _currentDataPosition = 0; private DynamicCachedReader() { @@ -110,8 +117,12 @@ namespace DynamORM var r = new DynamicCachedReader(); r.Init(firstDict.Keys.Count); + r._data.Add(new Data()); + + var data = r._data[r._currentDataPosition]; + for (int i = 0; i < firstDict.Keys.Count; i++) - r._types.Add(null); + data._types.Add(null); foreach (dynamic elem in (objects as IEnumerable)) { @@ -122,60 +133,60 @@ namespace DynamORM { object val = dict[k]; - r._cache.Add(val); + data._cache.Add(val); - if (r._types[c] == null && val != null) - r._types[c] = val.GetType(); + if (data._types[c] == null && val != null) + data._types[c] = val.GetType(); c++; } - r._rows++; + data._rows++; } for (int i = 0; i < firstDict.Keys.Count; i++) - if (r._types[i] == null) - r._types[i] = typeof(string); + if (data._types[i] == null) + data._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))); + data._schema = new DataTable("DYNAMIC"); + data._schema.Columns.Add(new DataColumn("ColumnName", typeof(string))); + data._schema.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int))); + data._schema.Columns.Add(new DataColumn("ColumnSize", typeof(int))); + data._schema.Columns.Add(new DataColumn("NumericPrecision", typeof(short))); + data._schema.Columns.Add(new DataColumn("NumericScale", typeof(short))); + data._schema.Columns.Add(new DataColumn("DataType", typeof(Type))); + data._schema.Columns.Add(new DataColumn("ProviderType", typeof(int))); + data._schema.Columns.Add(new DataColumn("NativeType", typeof(int))); + data._schema.Columns.Add(new DataColumn("AllowDBNull", typeof(bool))); + data._schema.Columns.Add(new DataColumn("IsUnique", typeof(bool))); + data._schema.Columns.Add(new DataColumn("IsKey", typeof(bool))); + data._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 = data._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[5] = data._types[ordinal]; + dr[6] = data._types[ordinal].ToDbType(); + dr[7] = data._types[ordinal].ToDbType(); dr[8] = true; dr[9] = false; dr[10] = false; dr[11] = false; - r._schema.Rows.Add(dr); + data._schema.Rows.Add(dr); - r._names.Add(dr[0].ToString()); - r._ordinals.Add(dr[0].ToString().ToUpper(), ordinal++); - r._types.Add((Type)dr[5]); + data._names.Add(dr[0].ToString()); + data._ordinals.Add(dr[0].ToString().ToUpper(), ordinal++); + data._types.Add((Type)dr[5]); dr.AcceptChanges(); } @@ -202,8 +213,6 @@ namespace DynamORM r.FillFromEnumerable(objects, mapper); r.IsClosed = false; - r._position = -1; - r._cachePos = -1; return r; } @@ -225,64 +234,68 @@ namespace DynamORM r.FillFromEnumerable(elementType, objects, mapper); r.IsClosed = false; - r._position = -1; - r._cachePos = -1; return r; } private void InitDataReader(IDataReader reader, int offset = 0, int limit = -1, Func progress = null) { - _schema = reader.GetSchemaTable(); - RecordsAffected = reader.RecordsAffected; - - Init(reader.FieldCount); - - int i = 0; - - for (i = 0; i < _fields; i++) + do { - _names.Add(reader.GetName(i)); - _types.Add(reader.GetFieldType(i)); + Init(reader.FieldCount); - if (!_ordinals.ContainsKey(reader.GetName(i).ToUpper())) - _ordinals.Add(reader.GetName(i).ToUpper(), i); - } + var data = _data[_currentDataPosition]; - int current = 0; - while (reader.Read()) - { - if (current < offset) + data._schema = reader.GetSchemaTable(); + data._rowsAffected = reader.RecordsAffected; + + int i = 0; + + for (i = 0; i < data._fields; i++) { - current++; - continue; + data._names.Add(reader.GetName(i)); + data._types.Add(reader.GetFieldType(i)); + + if (!data._ordinals.ContainsKey(reader.GetName(i).ToUpper())) + data._ordinals.Add(reader.GetName(i).ToUpper(), i); } - for (i = 0; i < _fields; i++) - _cache.Add(reader[i]); + int current = 0; + while (reader.Read()) + { + if (current < offset) + { + current++; + continue; + } - _rows++; - current++; + for (i = 0; i < data._fields; i++) + data._cache.Add(reader[i]); - if (limit >= 0 && _rows >= limit) - break; + data._rows++; + current++; - if (progress != null && !progress(this, _rows)) - break; - } + if (limit >= 0 && data._rows >= limit) + break; - IsClosed = false; - _position = -1; - _cachePos = -1; + if (progress != null && !progress(this, data._rows)) + break; + } - if (progress != null) - progress(this, _rows); + IsClosed = false; + data._position = -1; + data._cachePos = -1; + + if (progress != null) + progress(this, data._rows); + } while (reader.NextResult()); reader.Close(); } private void FillFromEnumerable(IEnumerable objects, DynamicTypeMap mapper) { + var data = _data[_currentDataPosition]; foreach (var elem in objects) { foreach (var col in mapper.ColumnsMap) @@ -292,17 +305,19 @@ namespace DynamORM if (col.Value.Get != null) val = col.Value.Get(elem); - _cache.Add(val); + data._cache.Add(val); } - _cache.Add(elem); + data._cache.Add(elem); - _rows++; + data._rows++; } } private void FillFromEnumerable(Type elementType, IEnumerable objects, DynamicTypeMap mapper) { + var data = _data[_currentDataPosition]; + foreach (var elem in objects) { foreach (var col in mapper.ColumnsMap) @@ -312,37 +327,38 @@ namespace DynamORM if (col.Value.Get != null) val = col.Value.Get(elem); - _cache.Add(val); + data._cache.Add(val); } - _cache.Add(elem); + data._cache.Add(elem); - _rows++; + data._rows++; } } private void CreateSchemaTable(DynamicTypeMap mapper) { - _schema = new DataTable("DYNAMIC"); - _schema.Columns.Add(new DataColumn("ColumnName", typeof(string))); - _schema.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int))); - _schema.Columns.Add(new DataColumn("ColumnSize", typeof(int))); - _schema.Columns.Add(new DataColumn("NumericPrecision", typeof(short))); - _schema.Columns.Add(new DataColumn("NumericScale", typeof(short))); - _schema.Columns.Add(new DataColumn("DataType", typeof(Type))); - _schema.Columns.Add(new DataColumn("ProviderType", typeof(int))); - _schema.Columns.Add(new DataColumn("NativeType", typeof(int))); - _schema.Columns.Add(new DataColumn("AllowDBNull", typeof(bool))); - _schema.Columns.Add(new DataColumn("IsUnique", typeof(bool))); - _schema.Columns.Add(new DataColumn("IsKey", typeof(bool))); - _schema.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool))); + var data = _data[_currentDataPosition]; + data._schema = new DataTable("DYNAMIC"); + data._schema.Columns.Add(new DataColumn("ColumnName", typeof(string))); + data._schema.Columns.Add(new DataColumn("ColumnOrdinal", typeof(int))); + data._schema.Columns.Add(new DataColumn("ColumnSize", typeof(int))); + data._schema.Columns.Add(new DataColumn("NumericPrecision", typeof(short))); + data._schema.Columns.Add(new DataColumn("NumericScale", typeof(short))); + data._schema.Columns.Add(new DataColumn("DataType", typeof(Type))); + data._schema.Columns.Add(new DataColumn("ProviderType", typeof(int))); + data._schema.Columns.Add(new DataColumn("NativeType", typeof(int))); + data._schema.Columns.Add(new DataColumn("AllowDBNull", typeof(bool))); + data._schema.Columns.Add(new DataColumn("IsUnique", typeof(bool))); + data._schema.Columns.Add(new DataColumn("IsKey", typeof(bool))); + data._schema.Columns.Add(new DataColumn("IsAutoIncrement", typeof(bool))); int ordinal = 0; DataRow dr = null; foreach (var column in mapper.ColumnsMap) { - dr = _schema.NewRow(); + dr = data._schema.NewRow(); dr[0] = column.Value.Column.NullOr(x => x.Name ?? column.Value.Name, column.Value.Name); dr[1] = ordinal; @@ -357,16 +373,16 @@ namespace DynamORM dr[10] = column.Value.Column.NullOr(x => x.IsKey, false); dr[11] = false; - _schema.Rows.Add(dr); + data._schema.Rows.Add(dr); - _names.Add(dr[0].ToString()); - _ordinals.Add(dr[0].ToString().ToUpper(), ordinal++); - _types.Add((Type)dr[5]); + data._names.Add(dr[0].ToString()); + data._ordinals.Add(dr[0].ToString().ToUpper(), ordinal++); + data._types.Add((Type)dr[5]); dr.AcceptChanges(); } - dr = _schema.NewRow(); + dr = data._schema.NewRow(); dr[0] = "#O"; dr[1] = ordinal; @@ -381,33 +397,38 @@ namespace DynamORM dr[10] = false; dr[11] = false; - _schema.Rows.Add(dr); + data._schema.Rows.Add(dr); - _names.Add("#O"); - _ordinals.Add("#O".ToUpper(), ordinal++); - _types.Add(mapper.Type); + data._names.Add("#O"); + data._ordinals.Add("#O".ToUpper(), ordinal++); + data._types.Add(mapper.Type); dr.AcceptChanges(); } private void Init(int fieldCount) { - _rows = 0; - _fields = fieldCount; - _names = new List(_fields); - _ordinals = new Dictionary(_fields); - _types = new List(_fields); - _cache = new List(_fields * 100); + _data.Add(new Data() + { + _rows = 0, + _fields = fieldCount, + _names = new List(fieldCount), + _ordinals = new Dictionary(fieldCount), + _types = new List(fieldCount), + _cache = new List(fieldCount * 100), + }); + + _currentDataPosition = _data.Count - 1; } /// Sets the current position in reader. /// The position. public void SetPosition(int pos) { - if (pos >= -1 && pos < _rows) + if (pos >= -1 && pos < _data[_currentDataPosition]._rows) { - _position = pos; - _cachePos = _position * _fields; + _data[_currentDataPosition]._position = pos; + _data[_currentDataPosition]._cachePos = _data[_currentDataPosition]._position * _data[_currentDataPosition]._fields; } else throw new IndexOutOfRangeException(); @@ -421,15 +442,14 @@ namespace DynamORM public void Close() { IsClosed = true; - _position = _rows; - _cachePos = -1; + _currentDataPosition = -1; } /// Gets a value indicating the depth of nesting for the current row. /// This implementation use this field to indicate row count. public int Depth { - get { return _rows; } + get { return _data[_currentDataPosition]._rows; } } /// Returns a System.Data.DataTable that describes the column metadata of the @@ -438,7 +458,7 @@ namespace DynamORM /// The System.Data.IDataReader is closed. public DataTable GetSchemaTable() { - return _schema; + return _data[_currentDataPosition]._schema; } /// Gets a value indicating whether the data reader is closed. @@ -448,24 +468,26 @@ namespace DynamORM /// Returns true if there are more rows; otherwise, false. public bool NextResult() { - _cachePos = (++_position) * _fields; + _currentDataPosition++; - return _position < _rows; + return _data.Count < _currentDataPosition; } /// Advances the System.Data.IDataReader to the next record. /// Returns true if there are more rows; otherwise, false. public bool Read() { - _cachePos = (++_position) * _fields; + var data = _data[_currentDataPosition]; - return _position < _rows; + data._cachePos = (++data._position) * data._fields; + + return data._position < data._rows; } /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. /// The number of rows changed, inserted, or deleted; 0 if no rows were affected or the statement /// failed; and -1 for SELECT statements. - public int RecordsAffected { get; private set; } + public int RecordsAffected { get { return _data[_currentDataPosition]._rowsAffected; } } #endregion IDataReader Members @@ -475,10 +497,15 @@ namespace DynamORM /// freeing, releasing, or resetting unmanaged resources. public void Dispose() { - _names.Clear(); - _types.Clear(); - _cache.Clear(); - _schema.Dispose(); + foreach (var data in _data) + { + data._names.Clear(); + data._types.Clear(); + data._cache.Clear(); + data._schema.Dispose(); + } + + _data.Clear(); } #endregion IDisposable Members @@ -487,14 +514,15 @@ namespace DynamORM /// Gets the number of columns in the current row. /// When not positioned in a valid record set, 0; otherwise, the number of columns in the current record. The default is -1. - public int FieldCount { get { return _fields; } } + public int FieldCount { get { return _data[_currentDataPosition]._fields; } } /// Return the value of the specified field. /// The index of the field to find. /// Field value upon return. public bool GetBoolean(int i) { - return (bool)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (bool)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -502,7 +530,8 @@ namespace DynamORM /// Field value upon return. public byte GetByte(int i) { - return (byte)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (byte)data._cache[data._cachePos + i]; } /// Reads a stream of bytes from the specified column offset into the buffer @@ -515,7 +544,9 @@ namespace DynamORM /// The actual number of bytes read. public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { - using (MemoryStream ms = new MemoryStream((byte[])_cache[_cachePos + i])) + var data = _data[_currentDataPosition]; + + using (MemoryStream ms = new MemoryStream((byte[])data._cache[data._cachePos + i])) return ms.Read(buffer, bufferoffset, length); } @@ -524,7 +555,8 @@ namespace DynamORM /// Field value upon return. public char GetChar(int i) { - return (char)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (char)data._cache[data._cachePos + i]; } /// Reads a stream of characters from the specified column offset into the buffer @@ -537,7 +569,9 @@ namespace DynamORM /// The actual number of characters read. public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { - using (MemoryStream ms = new MemoryStream((byte[])_cache[_cachePos + i])) + var data = _data[_currentDataPosition]; + + using (MemoryStream ms = new MemoryStream((byte[])data._cache[data._cachePos + i])) { byte[] buff = new byte[buffer.Length]; long ret = ms.Read(buff, bufferoffset, length); @@ -562,7 +596,7 @@ namespace DynamORM /// The data type information for the specified field. public string GetDataTypeName(int i) { - return _types[i].Name; + return _data[_currentDataPosition]._types[i].Name; } /// Return the value of the specified field. @@ -570,7 +604,8 @@ namespace DynamORM /// Field value upon return. public DateTime GetDateTime(int i) { - return (DateTime)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (DateTime)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -578,7 +613,8 @@ namespace DynamORM /// Field value upon return. public decimal GetDecimal(int i) { - return (decimal)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (decimal)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -586,7 +622,8 @@ namespace DynamORM /// Field value upon return. public double GetDouble(int i) { - return (double)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (double)data._cache[data._cachePos + i]; } /// Gets the System.Type information corresponding to the type of System.Object @@ -596,7 +633,7 @@ namespace DynamORM /// would be returned from System.Data.IDataRecord.GetValue(System.Int32). public Type GetFieldType(int i) { - return _types[i]; + return _data[_currentDataPosition]._types[i]; } /// Return the value of the specified field. @@ -604,7 +641,8 @@ namespace DynamORM /// Field value upon return. public float GetFloat(int i) { - return (float)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (float)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -612,7 +650,8 @@ namespace DynamORM /// Field value upon return. public Guid GetGuid(int i) { - return (Guid)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (Guid)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -620,7 +659,8 @@ namespace DynamORM /// Field value upon return. public short GetInt16(int i) { - return (short)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (short)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -628,7 +668,8 @@ namespace DynamORM /// Field value upon return. public int GetInt32(int i) { - return (int)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (int)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -636,7 +677,8 @@ namespace DynamORM /// Field value upon return. public long GetInt64(int i) { - return (long)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + return (long)data._cache[data._cachePos + i]; } /// Gets the name for the field to find. @@ -644,7 +686,7 @@ namespace DynamORM /// The name of the field or the empty string (""), if there is no value to return. public string GetName(int i) { - return _names[i]; + return _data[_currentDataPosition]._names[i]; } /// Return the index of the named field. @@ -652,8 +694,10 @@ namespace DynamORM /// The index of the named field. public int GetOrdinal(string name) { - if (_ordinals.ContainsKey(name.ToUpper())) - return _ordinals[name.ToUpper()]; + var data = _data[_currentDataPosition]; + + if (data._ordinals.ContainsKey(name.ToUpper())) + return data._ordinals[name.ToUpper()]; return -1; } @@ -663,7 +707,9 @@ namespace DynamORM /// Field value upon return. public string GetString(int i) { - return (string)_cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + + return (string)data._cache[data._cachePos + i]; } /// Return the value of the specified field. @@ -671,7 +717,9 @@ namespace DynamORM /// Field value upon return. public object GetValue(int i) { - return _cache[_cachePos + i]; + var data = _data[_currentDataPosition]; + + return data._cache[data._cachePos + i]; } /// Gets all the attribute fields in the collection for the current record. @@ -679,10 +727,12 @@ namespace DynamORM /// The number of instances of System.Object in the array. public int GetValues(object[] values) { - for (int i = 0; i < _fields; i++) - values[i] = _cache[_cachePos + i]; + var data = _data[_currentDataPosition]; - return _fields; + for (int i = 0; i < data._fields; i++) + values[i] = data._cache[data._cachePos + i]; + + return data._fields; } /// Return whether the specified field is set to null. @@ -690,7 +740,8 @@ namespace DynamORM /// Returns true if the specified field is set to null; otherwise, false. public bool IsDBNull(int i) { - return _cache[_cachePos + i] == null || _cache[_cachePos + i] == DBNull.Value; + var data = _data[_currentDataPosition]; + return data._cache[data._cachePos + i] == null || data._cache[data._cachePos + i] == DBNull.Value; } /// Gets or sets specified value in current record. @@ -700,8 +751,10 @@ namespace DynamORM { get { - if (_ordinals.ContainsKey(name.ToUpper())) - return _cache[_cachePos + _ordinals[name.ToUpper()]]; + var data = _data[_currentDataPosition]; + + if (data._ordinals.ContainsKey(name.ToUpper())) + return data._cache[data._cachePos + data._ordinals[name.ToUpper()]]; throw new IndexOutOfRangeException(String.Format("Field '{0}' not found.", name)); } @@ -712,7 +765,11 @@ namespace DynamORM /// Value of specified column. public object this[int i] { - get { return _cache[_cachePos + i]; } + get + { + var data = _data[_currentDataPosition]; + return data._cache[data._cachePos + i]; + } } #endregion IDataRecord Members