From 47dfc2c20f02018b07ae6039ab2ec5282fb4f860 Mon Sep 17 00:00:00 2001 From: ecosSystem Date: Tue, 27 Oct 2026 13:32:22 +0100 Subject: [PATCH] SQLRDD: CommandTimeout connection option Every statement ran with the ADO.NET provider's default timeout (30 s for SQL Server), and there was no way to change it. With tables of millions of rows a count, an index or a first page of a function-key order can take longer; the statement is then cancelled and reported as an error, which for a read means no rows. The new connection option CommandTimeout (seconds, 0 = no limit, default -1 = the provider's default) is applied to every SqlDbCommand before it runs. Co-Authored-By: Claude Opus 5.5 --- src/Runtime/XSharp.SQLRdd/Classes/Command.prg | 11 +++++++++++ src/Runtime/XSharp.SQLRdd/Classes/Connection.prg | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Runtime/XSharp.SQLRdd/Classes/Command.prg b/src/Runtime/XSharp.SQLRdd/Classes/Command.prg index 5aad8a2cce..9cb2b4800f 100644 --- a/src/Runtime/XSharp.SQLRdd/Classes/Command.prg +++ b/src/Runtime/XSharp.SQLRdd/Classes/Command.prg @@ -128,6 +128,13 @@ class SqlDbCommand inherit SqlDbHandleObject implements IDisposable return end constructor + /// Apply the connection's CommandTimeout (when set) to the command. + private method _ApplyTimeout() as VOID + if SELF:Connection:CommandTimeout >= 0 .and. SELF:DbCommand != null + SELF:DbCommand:CommandTimeout := SELF:Connection:CommandTimeout + endif + RETURN + private method CallBack(cTable as STRING) as VOID if withEvents self:CommandText := SELF:Connection:RaiseStringEvent(self, SqlRDDEventReason.CommandText, cTable, self:CommandText) @@ -158,6 +165,7 @@ class SqlDbCommand inherit SqlDbHandleObject implements IDisposable method GetSchemaTable() as DataTable try self:Connection:ForceOpen() + SELF:_ApplyTimeout() if ! SELF:_TryBindParameters() return null endif @@ -310,6 +318,7 @@ class SqlDbCommand inherit SqlDbHandleObject implements IDisposable if self:Connection:DbTransaction != null self:DbTransaction := self:Connection:DbTransaction endif + SELF:_ApplyTimeout() if ! SELF:_TryBindParameters() return null endif @@ -348,6 +357,7 @@ class SqlDbCommand inherit SqlDbHandleObject implements IDisposable if self:Connection:DbTransaction != null self:DbTransaction := self:Connection:DbTransaction endif + SELF:_ApplyTimeout() if ! SELF:_TryBindParameters() return null endif @@ -376,6 +386,7 @@ class SqlDbCommand inherit SqlDbHandleObject implements IDisposable if self:Connection:DbTransaction != null self:DbTransaction := self:Connection:DbTransaction endif + SELF:_ApplyTimeout() if ! SELF:_TryBindParameters() return false endif diff --git a/src/Runtime/XSharp.SQLRdd/Classes/Connection.prg b/src/Runtime/XSharp.SQLRdd/Classes/Connection.prg index 9dc87680fd..862bdd5bc7 100644 --- a/src/Runtime/XSharp.SQLRdd/Classes/Connection.prg +++ b/src/Runtime/XSharp.SQLRdd/Classes/Connection.prg @@ -151,6 +151,14 @@ class SqlDbConnection inherit SqlDbHandleObject implements IDisposable end get end property + /// + /// Time in seconds a statement may run before it is cancelled (0 = no limit, default -1 = the + /// ADO.NET provider's default, 30 seconds for SQL Server). + /// + /// A count or an index on a table with millions of rows can take longer than the default. A + /// statement that times out is reported like any other error, which for a read means no rows. + property CommandTimeout as long auto + /// Identifier Case as returned by the Ado.Net provider in the DataSourceInformation metadata collection. property IdentifierCase as System.Data.Common.IdentifierCase auto get private set /// Quoted Identifier Case as returned by the Ado.Net provider in the DataSourceInformation metadata collection. @@ -266,6 +274,10 @@ class SqlDbConnection inherit SqlDbHandleObject implements IDisposable if Int32.TryParse(strValue, out var cacheMs) self:ResultCacheMs := cacheMs endif + case "commandtimeout" + if Int32.TryParse(strValue, out var timeout) + self:CommandTimeout := timeout + endif otherwise builder:Add(key, strValue) end switch @@ -332,6 +344,7 @@ class SqlDbConnection inherit SqlDbHandleObject implements IDisposable LegacyFieldTypes := DEFAULT_LEGACYFIELDTYPES UseNulls := DEFAULT_USENULLS UseLocks := DEFAULT_USELOCKS + CommandTimeout := -1 LongFieldNames := DEFAULT_LONGFIELDNAMES TrimTrailingSpaces := DEFAULT_TRIMTRAILINGSPACES PageSize := DEFAULT_PAGESIZE