我有一个VB6应用程序,它将记录集作为其中一个函数的参数。我在.NET项目中使用ADODB来创建记录集并将其传递给VB6项目。当我通过连接数据库然后断开连接在VS2010中创建记录集时,一切都很好:
con.ConnectionString = "Provider=SQLOLEDB.1;Data Source=MyDB;Initial Catalog=IC;User ID=user;Password=pass"
rs.ActiveConnection = con
rs.Open("SELECT * FROM Table1")
rs.ActiveConnection = Nothing
但是,当我通过从.net DataTable复制数据来创建记录集时: rsRecordSet = New ADODB.Recordset
For Each dtDataColumn As DataColumn In dtDataTable.Columns
Select Case dtDataColumn.DataType.UnderlyingSystemType.ToString
Case "System.Boolean" : dteRecordSetDataType = DataTypeEnum.adBoolean
Case "System.Byte" : dteRecordSetDataType = DataTypeEnum.adUnsignedTinyInt
Case "System.Char" : dteRecordSetDataType = DataTypeEnum.adChar
Case "System.DateTime" : dteRecordSetDataType = DataTypeEnum.adDate
Case "System.Double" : dteRecordSetDataType = DataTypeEnum.adDouble
Case "System.Int16" : dteRecordSetDataType = DataTypeEnum.adSmallInt
Case "System.Int32" : dteRecordSetDataType = DataTypeEnum.adInteger
Case "System.Int64" : dteRecordSetDataType = DataTypeEnum.adBigInt
Case "System.SByte" : dteRecordSetDataType = DataTypeEnum.adTinyInt
Case "System.Single" : dteRecordSetDataType = DataTypeEnum.adSingle
Case "System.UInt16" : dteRecordSetDataType = DataTypeEnum.adUnsignedSmallInt
Case "System.UInt32" : dteRecordSetDataType = DataTypeEnum.adUnsignedInt
Case "System.UInt64" : dteRecordSetDataType = DataTypeEnum.adUnsignedBigInt
Case "System.Guid" : dteRecordSetDataType = DataTypeEnum.adGUID
Case "System.String" : dteRecordSetDataType = DataTypeEnum.adVarChar
Case Else : dteRecordSetDataType = DataTypeEnum.adVarChar
End Select
If dtDataColumn.AllowDBNull Then
faeRecordSetAttribute = FieldAttributeEnum.adFldIsNullable
Else
faeRecordSetAttribute = FieldAttributeEnum.adFldUnspecified
End If
rsRecordSet.Fields.Append(dtDataColumn.ColumnName, dteRecordSetDataType, dtDataColumn.MaxLength, faeRecordSetAttribute)
Next
rsRecordSet.CursorLocation = CursorLocationEnum.adUseClient
rsRecordSet.CursorType = CursorTypeEnum.adOpenDynamic
rsRecordSet.LockType = LockTypeEnum.adLockOptimistic
rsRecordSet.ActiveConnection = Nothing
rsRecordSet.Open()
For Each dtDataRow As DataRow In dtDataTable.Rows
rsRecordSet.AddNew()
For Each rsField As ADODB.Field In rsRecordSet.Fields
Select Case rsField.Type
Case DataTypeEnum.adBoolean : rsField.Value = Convert.ToBoolean(dtDataRow.Item(rsField.Name))
Case DataTypeEnum.adGUID : rsField.Value = "{" & dtDataRow.Item(rsField.Name).ToString & "}"
Case Else : rsField.Value = dtDataRow.Item(rsField.Name)
End Select
Next
Next
Return rsRecordSet
...我的VB6项目立即拒绝它,例如“在此上下文中不允许操作”和“被调用者(服务器[非服务器应用程序])不可用和消失;所有连接都无效。”调用可能已执行。(HRESULT异常:0x80010007(RPC_E_SERVER_DIED))“。我一直有一个不可能的时间调试这两个项目(它在一个点上工作),看看在VB6项目中记录集被拒绝的地方,但我感觉它发生在它甚至进入我的VB6功能之前。
我希望有人可以向我解释两种不同记录集之间的区别。某个记录集中是否有信息表明它曾一度连接到数据库源?有没有一种方法可以从我现有的数据表“选择”,以便记录集认为它从某个地方拉出来?
提前致谢!
答案 0 :(得分:4)
.Net默认为断开连接的记录集,但VB6没有。您在代码中打开的记录集是动态记录集,如果没有打开的连接,它就无法运行。动态cursortype意味着对记录集的所有更改都会立即发布到数据库。当您关闭连接时,您将无法再这样做了。您的错误表明当您尝试添加新记录时,动态光标会查找连接,但无法找到。
您可能有兴趣检查您的CursorLocation是否仍为adUseClient。它不应该;将类型设置为动态后,光标必须是服务器端。您的光标是静态的,或者您的位置是服务器。
因此,要创建一个断开连接的记录集,属性必须是:
.CursorLocation = adUseClient
.CursorType = adOpenStatic 'This is automatic as a result of the previous line
.LockType = adLockBatchOptimistic
这最后与在断开连接的记录集上进行批量更改有关,然后准备好为整个批次发布锁定,发布记录,然后执行冲突解决过程。无论如何,看看这对你有帮助。它应该。
多一点:如果您只是将您的位置设置为客户端,则类型将默认为静态。它是唯一适用于客户端的cursortype。有点意义;你正在使用本地"快照"您的数据是否在客户端。
Here是一个简单的解释,从1999年开始,当时这是最前沿的东西。 :)