I have the following SQL/Server function defined in C# to detect when a vehicle has refuelled. I keep a context of the last fuel used so that I don’t need to move a cursor back over the data:
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlDouble GetFuelRefill(SqlString ID, SqlString FuelLeft)
{
object _lastID = CallContext.GetData("lastID6");
object _fuelRefill = CallContext.GetData("fuelRefill");
double fuelRefill = _fuelRefill == null ? 0.0 : Convert.ToDouble(_fuelRefill);
object _lastFuelLeft = CallContext.GetData("lastFuelLeft");
double lastFuelLeft = _lastFuelLeft == null ? 0.0 : Convert.ToDouble(_lastFuelLeft);
double result = 0.0;
if ((_lastID == null) || (Convert.ToString(_lastID) != ID.Value) || (_lastFuelLeft == null))
{
fuelRefill = 0;
CallContext.SetData("lastFuelLeft", 0.0);
}
else if (!FuelLeft.IsNull)
{
double fl = Convert.ToDouble(FuelLeft.Value);
if ((fl > 0.0) && (lastFuelLeft > 0.0) && ((fl - lastFuelLeft) / fl * 100.0 >= 5.0))
fuelRefill += fl - lastFuelLeft;
CallContext.SetData("lastFuelLeft", FuelLeft.Value);
}
result = fuelRefill;
CallContext.SetData("lastID6", ID.Value);
CallContext.SetData("fuelRefill", fuelRefill);
return new SqlDouble(result);
}
For the purpose of repeating the problem I have created a small test table:
SequenceNo AssetID FuelLeft
1 PJ1 50
2 PJ1 49
3 PJ1 48
4 PJ1 98
5 PJ1 95
Then I execute the following command from SQL/Server Management Studio:
SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill
FROM TestTable ORDER BY SequenceNo
Which yields the following result that I expect:
SequenceNo Refill
1 0
2 0
3 0
4 50
5 50
However then I try executing the same query using ADO from VBScript:
const DatabaseName = "MyDB"
const DatabaseServer = "(local)"
const adOpenForwardOnly = 0
const adLockOptimistic = 3
Dim FSO : set FSO = CreateObject("Scripting.FileSystemObject")
Dim Conn : Set Conn = CreateObject("ADODB.Connection")
Conn.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Initial Catalog=" & DatabaseName & ";Server=" & DatabaseServer
Set Query = CreateObject("ADODB.Recordset")
Query.Open "SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill FROM TestTable ORDER BY SequenceNo", Conn, adOpenForwardOnly, adLockOptimistic
Set f = FSO.CreateTextFile("E:\Temp\Test.TXT", true)
do while not Query.EOF
f.WriteLine Query("SequenceNo") & ", " & Query("Refill")
Query.MoveNext
loop
Set FSO = Nothing
Query.Close
Conn.Close
The test.txt file contains the following:
1, 0
2, 0
3, 0
4, 0
5, 0
Doing some further debugging it appears that the call context isn’t being saved for the duration of the query, but I wondered if anyone knows why and a way to solve it?
After further experimentation I found two solutions. One was to place the query inside a simple stored procedure such as:
And the other was to change the VBS code to use a client-side cursor: