From aff9a23581da2cc59ef71b41c636db0349c48955 Mon Sep 17 00:00:00 2001 From: Gabriel Santos Date: Mon, 22 Dec 2025 09:21:49 -0500 Subject: [PATCH 1/2] fixed bug with null reads due to lack of decoration --- src/Gemstone.Web/APIController/ReadOnlyModelController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gemstone.Web/APIController/ReadOnlyModelController.cs b/src/Gemstone.Web/APIController/ReadOnlyModelController.cs index ba5c6fb4..b186af9d 100644 --- a/src/Gemstone.Web/APIController/ReadOnlyModelController.cs +++ b/src/Gemstone.Web/APIController/ReadOnlyModelController.cs @@ -359,7 +359,7 @@ public virtual async Task Search([FromBody] SearchPost postDat /// A object containing the pagination information or . [HttpPost, Route("PageInfo/{parentID?}")] [ResourceAccess(ResourceAccessType.Read)] - public virtual async Task GetPageInfo(SearchPost postData, string? parentID, CancellationToken cancellationToken) + public virtual async Task GetPageInfo([FromBody] SearchPost postData, string? parentID, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); TableOperations tableOperations = new(connection); From 3677278685717ba6a091ad0c6f011e18130a388d Mon Sep 17 00:00:00 2001 From: Gabriel Santos Date: Fri, 19 Dec 2025 13:18:48 -0500 Subject: [PATCH 2/2] change model controller to have a function to create table operations --- .../APIController/ReadOnlyModelController.cs | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/Gemstone.Web/APIController/ReadOnlyModelController.cs b/src/Gemstone.Web/APIController/ReadOnlyModelController.cs index b186af9d..c02f3ef6 100644 --- a/src/Gemstone.Web/APIController/ReadOnlyModelController.cs +++ b/src/Gemstone.Web/APIController/ReadOnlyModelController.cs @@ -55,10 +55,10 @@ private class ConnectionCache : IDisposable private readonly AdoDataConnection m_connection; - private ConnectionCache() + private ConnectionCache(ReadOnlyModelController controller) { m_connection = new AdoDataConnection(Settings.Default); - Table = new TableOperations(m_connection); + Table = controller.CreateTableOperation(m_connection); } public void Dispose() @@ -66,9 +66,9 @@ public void Dispose() m_connection.Dispose(); } - public static ConnectionCache Create(double expiration) + public static ConnectionCache Create(ReadOnlyModelController controller, double expiration) { - ConnectionCache cache = new(); + ConnectionCache cache = new(controller); MemoryCache.GetOrAdd(cache.Token, expiration, () => cache, Dispose); @@ -175,7 +175,7 @@ public ReadOnlyModelController() [HttpGet, Route("Open/{filterExpression}/{parameters}/{expiration:double?}")] public Task Open(string? filterExpression, object?[] parameters, double? expiration, CancellationToken cancellationToken) { - ConnectionCache cache = ConnectionCache.Create(expiration ?? 1.0D); + ConnectionCache cache = ConnectionCache.Create(this, expiration ?? 1.0D); cache.Records = cache.Table.QueryRecordsWhereAsync(filterExpression, cancellationToken, parameters).GetAsyncEnumerator(cancellationToken); @@ -237,7 +237,7 @@ public IActionResult Close(string token) public virtual async Task Get(string? parentID, int page, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); RecordFilter? filter = null; if (ParentKey != string.Empty && parentID is not null) @@ -267,7 +267,7 @@ public virtual async Task Get(string? parentID, int page, Cancell public virtual async Task Get(string sort, bool ascending, int page, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); RecordFilter? filter = null; IAsyncEnumerable result = tableOperations.QueryRecordsAsync(sort, ascending, page, PageSize, cancellationToken, filter); @@ -288,7 +288,7 @@ public virtual async Task Get(string sort, bool ascending, int pa public virtual async Task Get(string parentID, string sort, bool ascending, int page, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); RecordFilter filter = new() { FieldName = ParentKey, @@ -311,7 +311,7 @@ public virtual async Task Get(string parentID, string sort, bool public virtual async Task GetOne(string id, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); T? result = await tableOperations.QueryRecordAsync(new RecordRestriction($"{PrimaryKeyField} = {{0}}", id), cancellationToken).ConfigureAwait(false); return result is null ? @@ -332,7 +332,7 @@ public virtual async Task GetOne(string id, CancellationToken can public virtual async Task Search([FromBody] SearchPost postData, int page, string? parentID, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); RecordFilter[] filters = postData.Searches.ToArray(); if (ParentKey != string.Empty && parentID is not null) @@ -362,7 +362,7 @@ public virtual async Task Search([FromBody] SearchPost postDat public virtual async Task GetPageInfo([FromBody] SearchPost postData, string? parentID, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); RecordFilter[] filters = postData.Searches.ToArray(); if (ParentKey != string.Empty && parentID is not null) @@ -396,7 +396,7 @@ public virtual async Task GetPageInfo([FromBody] SearchPost po public virtual async Task GetPageInfo(string? parentID, CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); RecordFilter[] filters = []; if (ParentKey != string.Empty && parentID is not null) @@ -428,7 +428,7 @@ public virtual async Task GetPageInfo(string? parentID, Cancellat public virtual async Task New(CancellationToken cancellationToken) { await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); T? result = tableOperations.NewRecord(); return Ok(result); @@ -450,7 +450,7 @@ public virtual async Task GetMaxValue(string fieldName, Cancellat // Create a connection and table operations instance await using AdoDataConnection connection = CreateConnection(); - TableOperations tableOperations = new(connection); + TableOperations tableOperations = CreateTableOperation(connection); string tableName = tableOperations.TableName; string sql = $"SELECT MAX([{fieldName}]) FROM [{tableName}]"; @@ -467,5 +467,14 @@ protected virtual AdoDataConnection CreateConnection() { return new AdoDataConnection(Settings.Default); } + + /// + /// Creates any needed by the controller. + /// + /// A new . + protected virtual TableOperations CreateTableOperation(AdoDataConnection connection) + { + return new TableOperations(connection); + } } }