当尝试读取OracleDataReader时出现“在已关闭的对象上的无效操作”异常,该如何修复?

4
我正在使用 .Net Core 和 Oracle.ManagedDataAccess.Core 插件创建一个 Web API,该 API 访问 Oracle 数据库以检索 Blob 字段并将其作为字节数组返回。我创建了一个函数(getBlobfromDB),该函数从 SQL 数据库的加密字段中获取 Oracle 连接字符串,连接并使用 OraleDataReader 检索和返回 Blob 字段。但是当 OraleDataReader 尝试读取记录时,我收到了这个异常:“在关闭的对象上进行无效操作”。
当您搜索此问题时,最相关的答案是此 post
然而,我百分之百确定连接字符串上的用户具有访问权限,因为那是模式所有者,并且我还尝试将模式所有者添加到 Select 查询中(SELECT FIELD FROM SCHEMA_OWNER.TABLE WHERE ID =“”),但仍然出现相同的错误。
所以我尝试了另外两件事情,从同一数据库中的另一个表获取不同的VARCHAR字段,仍然出现相同的错误;并在不同的Oracle数据库上尝试,我能够成功地检索数据。我注意到服务器上的Oracle版本不同,工作的版本为12.2,而不工作的版本为11.2,这可能是原因?我不知道还能做或尝试什么,我将感激任何您能给我的帮助/建议。
这是简化的函数。
private OracleBlob getBlobfromDB(string sSystem, string sID)
        {
            string sSQL = String.Empty;
            string connString = String.Empty;
            OracleConnection oConn = new OracleConnection();

            if (string.IsNullOrWhiteSpace(sID) || string.IsNullOrWhiteSpace(sSystem) )
            {
                return null;
            }          

            sSQL = "SELECT BLOB_FIELD FROM TABLE WHERE ID = " + sID;
            connString = getConnectionString(sSystem); 

            try
            {
                using (oConn = new OracleConnection(connString))
                { 
                    oConn.Open();
                    OracleCommand oCom = new OracleCommand(sSQL, oConn);                   

                    OracleDataReader oDr = oCom.ExecuteReader();                    
                    if (oDr.HasRows)
                    {      
                        //I'm able to reach to this point before getting the exception
                        oDr.Read();
                        OracleBlob blob = oDr.GetOracleBlob(0);                        
                        // Clean up
                        oDr.Close();
                        oDr.Dispose();
                        oCom.Dispose();
                        return blob;
                    }
                    else
                    {
                        // Clean up
                        oDr.Close();
                        oDr.Dispose();
                        oCom.Dispose();
                        return null;
                    }

                }
            }
            catch (Exception x)
            {
                return null;
            }
            finally
            {
                oConn.Close();
            }
        }

在读取 blob 之前,你需要保持读者和连接的开放状态。 - undefined
这就是我正在做的事情,不是吗? - undefined
不,你返回的是一个可以用来读取 blob 内容的对象,但你还没有执行它。在完成这个 blob 对象之前,应该保持所有东西都是打开状态。 - undefined
对不起,我没明白你的意思,我的代码到底有什么问题?因为在我关闭连接之前,就出现了异常,出错的地方是在这一行:oDr.Read(); - undefined
1个回答

0

使用 Oracle.ManagedDataAccess 依赖项时,您不应该 Close() 连接,也不要使用 using 子句。似乎这个依赖项本身会随意关闭连接。

从您的代码中删除:using(){} 关键字和 oConn.Close()


2
我对关于移除using()关键字的说法感到惊讶。没有Using子句的闭合,我不知道如何完成清理工作。此链接表明我们应该使用using()来编写Oracle连接:https://www.oracle.com/tools/technologies/quickstart-dotnet-for-oracle-database.html你能给我们指出一份文件页面,指示我们不要使用using()吗? - undefined
这是错误和危险的建议。虽然它是被管理的,但你仍然必须注意处理底层连接的释放。否则驱动程序就不知道何时进行释放。事实上,遵循这个答案会随着时间的推移耗尽池中所有的连接,并导致非常难以跟踪的错误。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接