1

我在 C# 中定义了以下 SQL/Server 函数来检测车辆何时加油。我保留了上次使用的燃料的上下文,这样我就不需要将光标移回数据上:

[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);
}

为了重复这个问题,我创建了一个小测试表:

SequenceNo  AssetID   FuelLeft
1           PJ1       50
2           PJ1       49
3           PJ1       48
4           PJ1       98
5           PJ1       95

然后我从 SQL/Server Management Studio 执行以下命令:

SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill 
FROM TestTable ORDER BY SequenceNo

这会产生我期望的以下结果:

SequenceNo  Refill
1           0
2           0
3           0
4           50
5           50

但是,然后我尝试使用 VBScript 中的 ADO 执行相同的查询:

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

test.txt 文件包含以下内容:

1, 0
2, 0
3, 0
4, 0
5, 0

做一些进一步的调试,似乎在查询期间没有保存调用上下文,但我想知道是否有人知道为什么以及解决它的方法?

4

1 回答 1

0

经过进一步的实验,我找到了两种解决方案。一种是将查询放在一个简单的存储过程中,例如:

CREATE PROCEDURE sp_Test
AS
BEGIN
    SET NOCOUNT ON;
    SELECT SequenceNo,dbo.GetFuelRefill(AssetID,FuelLeft) AS Refill 
        FROM TestTable ORDER BY SequenceNo
END

另一个是更改 VBS 代码以使用客户端游标:

const DatabaseName = "MyDB"
const DatabaseServer = "(local)"
const adOpenForwardOnly = 0
const adLockOptimistic = 3
const adUseClient = 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.CursorLocation = adUseClient
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
于 2012-12-19T00:22:50.430 回答