2

I use FSharp.Data.SqlClient type providers to access SQL server database. So, I set up the types in F# something as follows:

type ClmDB = SqlProgrammabilityProvider<ClmSqlProviderName, ConfigFile = AppConfigFile>
type ResultDataTable = ClmDB.dbo.Tables.ResultData
type ResultDataTableRow = ResultDataTable.Row

and then I use it something like that:

let saveResultData (r : ResultData) (conn : SqlConnection) =
    let t = new ResultDataTable()
    let newRow = r.addRow t
    t.Update(conn) |> ignore
    newRow.resultDataId

where ResultData is some type, which "knows" how to convert itself into a row of ResultDataTable (ResultDataTableRow). The extension r.addRow t does that.

Everything is great, except that the row that I am inserting might be fairly large (25-30 MB in size) and so, I have a bad feeling that t.Update(conn) might randomly time out especially due to nearly 100% processor load (the computational system core is designed to consume all processing resources, though at low priority). Hovering over t.Update does not show any way to specify a timeout and any timeout at the level of connection is related, well, to a connection, not to the insert transaction ☹.

So, the question is how to specify timeout for an Update transaction.

Thanks a lot!

20190116 update - So far t.Update(conn) above is holding up without timeouts on my machine while inserting 95MB data rows at 100% below normal load of some other stuff running there. I have not yet measured the actual time for such transactions. If I do, then I will update this.

  • Hi, have you try to add timeout on connections string ? I m looking about FSharp.Data.SqlClient but i didn’t see parameters . – Sanpas Jan 09 '19 at 06:30
  • 1
    @pascalsanchez According to specification, connection string time out is for connection to open, not for the command to execute: https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlconnection.connectiontimeout?view=netframework-4.7.2 :( But, with the absence of anything else it is worth a try. – Konstantin Konstantinov Jan 09 '19 at 10:38
  • Sorry . Yes i have try to read thoses documentation today but i didn't find relevant information. i'm take time to look. By this issues https://github.com/fsprojects/FSharp.Data.SqlClient/issues/98 they mention the existance off CommandTimeout – Sanpas Jan 09 '19 at 10:42
  • @pascalsanchez I am looking at the source: https://github.com/fsprojects/FSharp.Data.SqlClient/blob/master/src/SqlClient/DataTable.fs#L78-L79 and it looks that command time out for table `Update` is **not set** :( – Konstantin Konstantinov Jan 09 '19 at 11:26
  • I have see the same. You didn’t have way to change your code for use some other functions that provided timeout ? Or other way was to open issues on github i thibk it’s the good way. Îm sorry for bad helping but i didn’t work using F# at today. – Sanpas Jan 10 '19 at 06:21
  • @pascalsanchez Thanks for your help. I opened a ticket with developer: https://github.com/fsprojects/FSharp.Data.SqlClient/issues/324 Let's see if they reply. – Konstantin Konstantinov Jan 10 '19 at 08:37

1 Answers1

1

You cannot specify timeout for Update method of a provided DataTable because the current Type Provider implementation does not provision for such feature.

However, as the documentation notes you may have few options for customizing the default behavior.

In addition, as your use case resembles an insert of a single row into the table I'd stick to an implementation with the help of SqlCommandProvider using its constructor's commandTimeOut optional parameter for setting the desired timeout value timespan, as in a snippet below:

type AddRow = SqlCommandProvider<"path to the parameterized INSERT statement", designTimeConnection> 
..............................
(new AddRow(runTimeConnection, commandTimeOut=timespan)).Execute(...arg=value...) |> ignore
Gene Belitski
  • 10,270
  • 1
  • 34
  • 54
  • Yeah. I really do not want to go that way as this effectively requires writing SQL statements in F#. I don’t think that this is a proper way to go. On the other side, I cannot specify a timeout for `Update` method unless I fork and actually **do** that. Given that I already have "local" bug fixes for two open source F# / C# projects, that would make it third ☹. Which means that I will have at least three sources, which I would have to manually reconcile with the repos. This is getting gross ☹. I opened a ticket with the developers and let’s see if it works out. – Konstantin Konstantinov Jan 12 '19 at 02:33
  • @KonstantinKonstantinov: Well, the up to date experience of using this TP in enterprise production context indicates that usual use pattern comes down to _ADO with statically controlled record structure and field types_. Entities as the custom `DataTable` cater more for non-production usage kind of exploratory programming and consciously may not carry certain features. For example, lack of asynchronicity support in `DataTable` methods. – Gene Belitski Jan 13 '19 at 16:07
  • The asynchronous "support" is a no-brainer in F# due to `async {...}` structure, `MailboxProcessor`, etc... So, I don't think that we need this C#-like zoo of sync/async methods in F# . My point is that currently if I want a timeout on table `Update` method, then the only way to get that (thanks to open source) is to clone the repo and just "make it happen". On the positive side, I think that I am not (yet) hitting timeouts inserting 30 MB rows of binary data. Perhaps it is worth moving such BLOBs into a file storage but this is beyond this question. – Konstantin Konstantinov Jan 13 '19 at 22:38
  • It would be in the true spirit of OSS if you, instead of forking and keeping locally, will submit PRs for the bugs and features you've addressed, indeed. – Gene Belitski Jan 14 '19 at 15:38
  • I did that for both of the local forks. Since nothing happened with the open tickets for months I just moved on. Here is one bug: https://github.com/mathnet/mathnet-numerics/issues/595 It's been out for about 5 months :( – Konstantin Konstantinov Jan 14 '19 at 17:49
  • I finally gave up, generated SQL INSERT / UPDATE statements (I only needed to do that for two "data heavy" tables with under 20 columns each), copy-pasted to F#, replaced some SQL stuff, added connection timeout, and under 15 minutes the whole thing is kicking and screaming with no changes to the callers! Thanks again for the advice! – Konstantin Konstantinov Jan 25 '19 at 20:59