Skip to content

Commit 8bbe363

Browse files
Merge pull request #339 from VTJDailey/Issue_324
Allow timeout on data table Update commands
2 parents 52f8932 + 572fb1c commit 8bbe363

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

src/SqlClient/DataTable.fs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type DataTable<'T when 'T :> DataRow>(selectCommand: SqlCommand, ?connectionStri
3939

4040
member private this.IsDirectTable = this.TableName <> null
4141

42-
member this.Update(?connection, ?transaction, ?batchSize, ?continueUpdateOnError) =
42+
member this.Update(?connection, ?transaction, ?batchSize, ?continueUpdateOnError, ?timeout: TimeSpan) =
4343
// not supported on all DataTable instances
4444
match selectCommand with
4545
| null -> failwith "This command wasn't constructed from SqlProgrammabilityProvider, call to Update is not supported."
@@ -56,6 +56,8 @@ type DataTable<'T when 'T :> DataRow>(selectCommand: SqlCommand, ?connectionStri
5656
use dataAdapter = new SqlDataAdapter(selectCommand)
5757
use commandBuilder = new SqlCommandBuilder(dataAdapter)
5858
use __ = dataAdapter.RowUpdating.Subscribe(fun args ->
59+
timeout |> Option.iter (fun x -> args.Command.CommandTimeout <- int x.TotalSeconds)
60+
5961
if args.Errors = null && args.StatementType = StatementType.Insert
6062
&& defaultArg batchSize dataAdapter.UpdateBatchSize = 1
6163
then

tests/SqlClient.Tests/DataTablesTests.fs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ type DataTablesTests() =
216216
let rowsInserted = t.Update(conn, tran)
217217
Assert.Equal(1, rowsInserted)
218218

219+
219220
[<Fact>]
220221
member __.SqlCommandTableUpdate() =
221222
use cmd =
@@ -229,6 +230,43 @@ type DataTablesTests() =
229230
row.ModifiedDate <- DateTime.Now.Date
230231
let rowsAffected = t.Update(conn, tran)
231232
Assert.Equal(1, rowsAffected)
233+
234+
[<Fact(Skip = "Don't execute for usual runs. Too slow.")>]
235+
member __.SqlCommandTable_RespectsTimeout() =
236+
let tbl = new AdventureWorksDataTables.Production.Tables.Location()
237+
238+
use conn = new SqlConnection(connectionString = adventureWorks)
239+
conn.Open()
240+
use tran = conn.BeginTransaction()
241+
242+
tbl.AddRow("test", Some 12.12M, Some 23.23M, Some System.DateTime.UtcNow)
243+
let rowcount = tbl.Update(connection = conn, transaction = tran, timeout = TimeSpan.FromSeconds(5.0))
244+
245+
let row = tbl.Rows |> Seq.head
246+
247+
row.Name <- "Slow Trigger"
248+
249+
let sw = new System.Diagnostics.Stopwatch()
250+
sw.Start()
251+
252+
let mutable completed = false
253+
try
254+
let rowcount = tbl.Update(connection = conn, transaction = tran, timeout = TimeSpan.FromSeconds(5.0))
255+
completed <- true
256+
with
257+
| ex ->
258+
()
259+
260+
sw.Stop()
261+
262+
if completed then
263+
failwith "Update should not have completed. Operation should have taken 15 seconds and timeout was set to 5 seconds."
264+
else if sw.Elapsed.TotalSeconds > 6.0 then
265+
failwith "Timeout was set to 5 seconds. Operation should have failed earlier than this"
266+
else if sw.Elapsed.TotalSeconds < 4.0 then
267+
failwith "Timeout was set to 5 seconds. Operation should have lasted longer than this. The test may be set up incorrectly"
268+
269+
232270

233271
[<Fact>]
234272
member __.NewRowAndBulkCopyWithTrsansactionScope() =

tests/SqlClient.Tests/extensions.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ IF OBJECT_ID(N'Sales.UnitedKingdomOrders') IS NOT NULL
7272
DROP TABLE Sales.UnitedKingdomOrders
7373
GO
7474

75+
--TRIGGERS
76+
IF OBJECT_ID(N'Production.tr_Location_Slow') IS NOT NULL
77+
DROP TRIGGER Production.tr_Location_Slow
78+
GO
79+
7580
-- SYNONYMs
7681

7782
IF OBJECT_ID(N'HumanResources.GetContactInformation') IS NOT NULL
@@ -324,6 +329,18 @@ GO
324329

325330

326331
GO
332+
333+
--TRIGGERS
334+
CREATE TRIGGER Production.tr_Location_Slow ON Production.Location FOR UPDATE, DELETE
335+
AS
336+
DECLARE @count int = (SELECT COUNT(*) FROM inserted WHERE Name = 'Slow Trigger')
337+
338+
IF @count > 0
339+
BEGIN
340+
WAITFOR DELAY '00:00:15'
341+
END
342+
GO
343+
327344
--SYNONYMS
328345

329346
CREATE SYNONYM HumanResources.GetContactInformation FOR dbo.ufnGetContactInformation;

0 commit comments

Comments
 (0)