Closed replicaJunction closed 4 years ago
I think the problem is around here: https://github.com/fsprojects/SQLProvider/blob/6a089a02a710f8e3fc7bb2df175dcf3a3c713612/src/SQLProvider/SqlDesignTime.fs#L408
Instead of return ()
it could do Aync.Catch
and then in case of error, return the error, not empty.
Do you get this compile, do you want to send a PR?
I'm afraid I'm having some trouble getting a working build environment set up on my machine - I can't compile the code as-is before I make any changes.
This should be now fixed in the most recent version of SQLProvider (Nuget package).
After this fix, it appears that I am getting a compile error for every InvokeAsync in my project. I'm building with Visual Studio, but compiling to netstandard2.0, while having also tried netcoreapp3.1. I'm not able to try out net472 on this project, as there are other netcoreapp3.1 depending on this project. The compile error is error FS1109: A reference to the type 'Microsoft.FSharp.Core.FSharpChoice``2.Choice2Of2' in assembly 'FSharp.Core' was found, but the type could not be found in that assembly
along with a corresponding error FS0193: The module/namespace 'Microsoft.FSharp.Core.FSharpChoice``2' from compilation unit 'FSharp.Core' did not contain the namespace, module or type 'Choice2Of2'
. Downgrading back to 1.1.76 removes the errors from the build, and, upon restarting Visual Studio, removes the errors from the IDE.
If I use Choice<_,_>
and Choice2Of2
directly in my code, it doesn't appear to have any issues.
I thought I was going crazy when the same thing happened to me. Thanks for pointing it out.
I can also confirm this behavior using a library project targeting .NET Standard 2.1. Version 1.1.76 (from NuGet) works without error, and versions 1.1.78 and 1.1.79 both cause the error message detailed above.
Sounds strange, I'm using dotnet.exe 3.1.101 targetting netcoreapp2.0 and calling async stored procedure works fine.
Now, one thing I did for over 1.1.76 was that I changed the FSharp.Core from 4.2.3 to 4.5.4 So somehow something is now referencing an incorrect core-version. What version does your project use? Should I revert back that change?
My project uses FSharp.Core 4.7.0. I wonder if they made changes to the Choice
type?
Maybe the real reason is actually the Choice-record on the quotation code. Let me try to fix it another way then. Try the 1.1.80, please, just pushed that to the NuGet.
I assume you know using exceptions as a flow control is a bad practice in .NET:
But I totally agree this as an issue, exceptions shouldn't be swallowed on any conditions.
I can try this out shortly. However, I wanted to emphasize that I was not using dotnet.exe at all, but, rather, using Visual Studio while targetting netcoreapp3.1, which, I assume, uses F# compiler running on .NET Framework. My previous attempts using dotnet.exe wouldn't work. I think something to do with not finding dependencies or something.
From a philosophical point of view, I take the stance that "exceptions should be for exceptional cases." If I can anticipate something going wrong, I should explicitly address that case before it could happen.
That said, the reason this issue came to my attention was that I was writing code to use someone else's stored procedures that would sometimes raise errors. In this scenario, I don't have the ability to change the stored procedure. I can do my best to code around the cases I know will fail, but I need to be able to handle failures as well (log the exception and the faulty data, stop executing that branch, etc.).
Somewhere along the pipeline, those SQL errors get translated to SQLExceptions. (I think that's in SqlClient itself, so that's no fault of this library.) I'd be much happier if that was translated to some kind of "SqlResult" class instead, but I've got to work with the tools I'm given. :)
Unfortunately, version 1.1.80 fixes the previous issue and allows the code to compile, but it doesn't seem to fix the original problem. I still don't see the exception when using InvokeAsync.
Running normal test with name John
Normal result succeeded:
<null>
Running async test with name John
Async result succeeded:
<null>
Running normal test with name NotARealName
Normal result failed:
System.Data.SqlClient.SqlException (0x80131904): Could not find name [NotARealName]
...stack trace...
ClientConnectionId:21bd88e4-0341-43e4-8679-42f31969843a
Error Number:50001,State:1,Class:16
Running async test with name NotARealName
Async result succeeded:
<null>
@TheJayMann I haven't been able to compile F# projects using this library using dotnet build
at all. I believe that's the issue described in #580, #626, and #645. Using MSBuild (either from VS or from the command line) seems to avoid the issue.
Ok, found it. It wasn't Async.Catch related, instead the Async.AwaitIAsyncResult in the source code swallowed the exception generated by ExecuteNonQueryAsync. Nuget 1.1.81 is now pushed and I'm quite sure it will fix this problem. :-)
P.S. I can build via both dotnet and VS, but I don't know what I've done differently than others.
Description
Some stored procedures return result sets of data, but others just return int status codes to indicate success or failure. SQLProvider appears to ignore those status codes, and calling
Invoke
orInvokeAsync
on one of those procedures returnsUnit
orAsync<Unit>
respectively.When one of these procedures throws an error,
Invoke
raises aSqlException
with the text of the error thrown from the procedure. This can be caught using a normaltry...with
block. However, theInvokeAsync
method does not appear to catch this error, and the code continues as if the procedure was successful.Also mentioned in the last comment in #535.
Repro steps
Use this SQL to create a table, procedure, and some example rows:
Now, run this F# code:
These are the results of running the above code in F# interactive:
Finally, for comparison, modify and run the SQL by uncommenting the last SELECT line and commenting the RETURN line at the end. Repeat the F# code and compare the results.
Expected behavior
InvokeAsync
should returnChoice2Of2
with an exception in both test cases.Actual behavior
In the first case,
InvokeAsync
appears to succeed, whileInvoke
returns a clear failure message. In the second test case, bothInvoke
andInvokeAsync
failed as expected.Known workarounds
I can think of two workarounds:
Neither of these are great options.
Related information