From 0bbd3a66bf441e26685cfe5813fe69ddd9e781ed Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:19:02 -0300 Subject: [PATCH] Records read by MemoryDataReader can always be cached because the cursor is fully consumed during the read operation. (#1085) --- .../GxClasses/Data/GXDataCommon.cs | 21 +++--- .../GxClasses/Data/GXDataMemory.cs | 67 ++++++++++++++++--- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs index 1eb63d2f7..023f69c00 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataCommon.cs @@ -2225,16 +2225,19 @@ public GxDataReader( IGxConnectionManager connManager, GxDataRecord dr, IGxConne public void AddToCache(bool hasNext) { - if (hasNext) + if (!(reader is MemoryDataReader)) { - object[] values = new object[reader.FieldCount]; - m_dr.GetValues(reader, ref values); - block.Add(values); - } - else - { - SqlUtil.AddBlockToCache(key, new CacheItem(block, false, pos, readBytes), con, expiration != null ? (int)expiration.ItemSlidingExpiration.TotalMinutes : 0); - Close(); + if (hasNext) + { + object[] values = new object[reader.FieldCount]; + m_dr.GetValues(reader, ref values); + block.Add(values); + } + else + { + SqlUtil.AddBlockToCache(key, new CacheItem(block, false, pos, readBytes), con, expiration != null ? (int)expiration.ItemSlidingExpiration.TotalMinutes : 0); + Close(); + } } } diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs index 5ac71ea95..3cc67619f 100644 --- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs +++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataMemory.cs @@ -517,6 +517,7 @@ public MemoryDataReader(IDataReader reader, IGxConnection connection, GxParamete { this.key = SqlUtil.GetKeyStmtValues(parameters, stmt, isForFirst); this.expiration = expiration; + AddToCache(false); } } @@ -602,26 +603,21 @@ public bool Read() else this._currentIndex = 0; - if (cached) - { - AddToCache(this._records.Count > 0); - } - return this._records.Count > 0; } public void AddToCache(bool hasNext) { - if (hasNext) + foreach (MemoryDataRecord record in this._records) { object[] values = new object[FieldCount]; - MemoryDataRecord record = this._records[0]; record.GetValues(values); + foreach(object obj in values) + { + readBytes += MemoryDataHelper.SizeInBytes(obj); + } block.Add(values); } - else - { - SqlUtil.AddBlockToCache(key, new CacheItem(block, false, block.Count, readBytes), con, expiration != null ? (int)expiration.ItemSlidingExpiration.TotalMinutes : 0); - } + SqlUtil.AddBlockToCache(key, new CacheItem(block, false, block.Count, readBytes), con, expiration != null ? (int)expiration.ItemSlidingExpiration.TotalMinutes : 0); } public int RecordsAffected { @@ -853,6 +849,55 @@ public object this[int i] class MemoryDataHelper { + internal static int SizeInBytes(object value) + { + + if (value == null || value == DBNull.Value) + return 0; + + Type type = value.GetType(); + + if (type == typeof(bool)) + { + return 1; + } + if (type == typeof(byte[])) + { + return ((byte[])value).Length; + } + if (type == typeof(DateTime)) + { + return 8; + } + if (type == typeof(Decimal)) + { + return 12; + } + if (type == typeof(Double)) + { + return 8; + } + if (type == typeof(Guid)) + { + return 16; + } + if (type == typeof(Int16)) + { + return 2; + } + if (type == typeof(Int32)) + { + return 4; + } + if (type == typeof(Int64)) + { + return 8; + } + if (type == typeof(string)) + return (10 + (2 * ((string)value).Length)); + + return 0; + } #region Copy objects public static object GetCopyFrom(object value)