【问题标题】:Creating a copy of a recordset in a Session variable在 Session 变量中创建记录集的副本
【发布时间】:2015-12-14 16:21:16
【问题描述】:

这是我在这里提出的问题的后续内容> Converting an HTML table to JSON to pass to an AJAX call for downloading as a CSV

我有一个报告页面,可以将多个记录集输出为图形和表格,但还有“下载为 CSV 文件”的按钮并输出一个 CSV 就可以了。

问题是我想将存储过程的输出设置为 Session("DATA") 变量,然后在内存中创建数据的“副本”,这样每当按下“下载”按钮时,我就可以查找 Session("DATA") 变量,如果存在则输出。

问题在于,当我将记录集对象设置为指向 Session 时,它是引用的,因此一旦它遍历所有在页面上输出它们的记录集,则 Session 为空(或在所有记录集的末尾- 所以它是一个没有数据的对象)

如何创建记录集的“副本”而不是指针,以便会话中始终包含完整的记录集,例如

Set Session("DATA") = objCon.Execute(strSQL) '* returns multiple recordsets

Set objRS = Session("DATA")

Do While Not objRS.EOF......

'* BUT now when I want to access Session("DATA") it is at the start of all the recordsets and not a spent, EOF of the last recordset due to me looping through objRS

我可以有一个循环遍历记录集并进行复制的函数,但这似乎需要付出很多努力和提高性能,我认为必须有一种方法可以以某种方式复制会话的记录集而无需多次循环.

如果我必须创建一个“复制”对象函数,那么我想我必须这样做,但是在 ASP CLASSIC 中是否没有更简单的方法来创建对象的副本而不是引用指针?

【问题讨论】:

  • 您在 objCon 中使用的游标类型是什么? msdn.microsoft.com/en-us/library/windows/desktop/… 如果是 adOpenStatic,您可以将光标移回开头,例如objRS.MoveFirst
  • 我有一个复杂的数据类,它支持断开连接的记录集,要么返回记录计数(记录集设置为 objRecordset.CacheSize = 20 ob​​jRecordset.CursorLocation = adUseClient objRecordset.LockType = adLockReadOnly)-> 显然我需要移动到输出的多个记录集中的第一个记录集,而不仅仅是一个记录集中的第一个记录。如果我无法轻松创建记录集的副本,我正在考虑使用 JS 按 ID 将表复制到 Excel 中。

标签: session memory asp-classic ado recordset


【解决方案1】:

您可以使用GetRows 将整个记录集读入一个数组:

'GetDataSet
'   Returns a table of data based on the supplied SQL statement and connection string.
'Parameters:
'   sqlString (string) - The SQL string to be sent. This can be either a valid SQL string or an Application setting
'                           specified using the '@' prefix (e.g. @GET_USERNAME)
'   connString (string) - The database connection string. Either a valid connection string, an Application setting
'                           (using the '@' prefix, e.g. @CONN_STRING) or an AMC (AppModeConnection string).
'Usage:
'   dataSet = GetDataSet(sqlString, connString)
'Description:
'   This function generates a table of information in a 2 dimensional array.  The first dimension represents the columns
'   and the second the rows.  If an error occurs while the routine is executing the array and the base index (0,0) is set 
'   to C_ERROR, (0,1) to the VBScript error index, and (0,2) to the VBScript error description.
'Notes:
'   Updated this function to take advantage of the AppModeConnection feature.
'Revisions:
'   30/09/2015  1.1     Added facility to allow recovery of Application settings as Query and connection strings using 
'                       '@', (e.g.: ds = GetDataSet("@GET_USER_DETAIL", "@CONN_DATABASE")
'   25/09/2015  1.0     Added AMC support for Classic ASP. The system will test to see if there is a valid connection 
'                       string based on the current application mode and the connection string provided (e.g. if the 
'                       connection string is 'CONN_DATABASE' and the application mode is 'DEV' then the final connection
'                       string will be 'CONN_DATABASE_DEV'. A connection string should be present to cover this.
' < 25/09/2015  0.1     Bug ironed out that prevented closing of the database.
' < 25/09/2015  0.0     Initial version.
function GetDataSet(ByVal sqlString, ByVal connString)
    'Test to see if there's an application connection string first...
    If Left(connString, 1) = "@" Then
        connString = Application(Mid(connString, 2))
    Else
        Dim amc
        amc = AppModeConnection(connString)
        If amc <> "" then connString = amc
    End If
    'Test the SQL string to see if it's stored as an Application setting...
    If Left(sqlString, 1) = "@" Then sqlString = Application(Mid(sqlString, 2))
    'Define the initial output...
    dim rV, rs
    If  (Application("APP_MODE") =  Application("MODE_DEV")  And  Application("DEV_TRAP_ERRORS")) Or _
        (Application("APP_MODE") <> Application("MODE_DEV")) Then On Error Resume Next
        'Define and open the recordset object...
        set rs = Server.CreateObject("ADODB.RecordSet")
        rs.Open sqlString, connString, 0, 1, 1
        'Initialise an empty value for the containing array...
        redim rV(0,0)
        rV(0,0) = C_NO_DATA
        'Deal with any errors...
        if not rs.EOF and not rs.BOF then
            'Store the data...
            rV = rs.GetRows()
            'Tidy up...
            rs.close
            set rs = nothing
            select case err.number
                case 3021   'No data returned
                    'Do nothing as the initial value will still exist (C_NO_DATA)
                case 0      'No error
                    'Do nothing as data has been returned
                case else
                    redim rV(4,0)
                    rV(C_COL_IDENTIFIER,0) = C_ERROR
                    rV(C_COL_ERROR_ID,0) = err.number
                    rV(C_COL_ERROR_MESSAGE,0) = err.description
                    rV(C_COL_SQL,0) = sqlString
                    rV(C_COL_CONNECTION,0) = "Withheld"
            end select
        end if
    on error goto 0
    'Return the array...
    GetDataSet = rV
end function

这是我自己的深度版本,它使用连接字符串等做了一些时髦的东西,所以请随意使用它,但请注意,您必须设置连接字符串等的处理。在代码中,不过,您需要的是核心元素 - GetRows

您不需要设置任何 Session 变量,只需按照marekful's answer 对您的帖子进行处理即可。您可以使用一个简单的For...Next 循环和一个数组来做到这一点。

要使用上面的函数,只需声明您的 SQL 并像这样调用它...

Dim ds, sql
sql = "EXEC prc_get_report_data "
ds = GetDataSet(sql, "@my_conn")

(注意:阅读有关连接字符串的代码 cmets)。

由此返回的数组显然是基于零的二维数组,其中 x = 列,y = 行:

ds(x, y)

我倾向于定义常量来覆盖列名,将它们与数据库中的等价物匹配...

Const COL_ID = 0 'Column 0 is the ID field (note zero based)
Const COL_TITLE = 1 'Title field
Const COL_DESCRIPTION = 2 'Description field

...等等。

然后你就可以轻松引用它们了:

If ds(COL_ID, row) = 14 Then

使用UBound 函数获取数组的范围...

Dim row, rows
For rows = 0 To UBound(ds, 2) '2 is the second dimension of the array (note not zero based
    If ds(COL_ID, row) = avalue Then

你明白了。

【讨论】:

  • 嗨,问题是这是一个很大的系统,有很多报告,每个报告都有很多表——这就是我从存储的过程中返回多个记录集的原因。除了大量不同的列名之外,使用数组 GetNoRows() 是一个想法。我认为断开连接的记录集的行为类似于数组,但是当我转到“ajax 页面”来显示数据时,我得到一个“当前提供程序不支持从一次执行中返回多个记录集”。从 Session 上的 Session("Data").NextRecordset 调用中的记录集(输出第一个记录集后)
猜你喜欢
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
  • 2013-12-22
  • 1970-01-01
相关资源
最近更新 更多