C# WinForm项目从Oracle读取BLOB文件保存到本地问题排查
C# Winform 读取Oracle BLOB字段存储到本地代码问题修复
现有代码核心问题
- 字符串转义错误:定义
tempDir的代码存在语法错误,C#中反斜杠为转义字符,网络路径要么用双反斜杠全转义,要么加@声明为逐字字符串,你写的末尾\还会和后接的引号冲突,编译都无法通过。 - 查询字段不匹配:你写的SQL查询只返回了
id、name、contenttype三个字段,没有包含存储文件的BLOB字段,且GetOracleBlob(1)读取的是name字段,该字段为字符串类型,根本不是BLOB格式,直接触发类型转换错误。 - 资源泄漏风险:
OracleDataReader、FileStream都没有用using包裹,异常场景下会出现资源未释放、文件句柄占用的问题。 - 逻辑冗余错误:你写了遍历
dataTable的循环,但硬编码了SQL的查询条件id=3,注释掉了参数化代码,循环完全不生效,每次查询的都是同一条记录;且数据库连接创建、打开的逻辑写在循环内,每次循环都新建连接,性能极低。 - 无结果校验:没有判断
OracleDataReader.Read()的返回值,如果查询无数据,直接读取字段会抛空引用/索引越界异常。
修复后可运行代码
// 逐字字符串避免转义问题,也可以替换为本地下载目录:Environment.GetFolderPath(Environment.SpecialFolder.Downloads) string tempDir = @"\\NB17-KP-239\Downloads\"; // 连接字符串放到循环外,复用连接 string oradbConString = "Data Source = localhost; Persist Security Info = True; User ID = homeuser; Password = admin;"; using (OracleConnection oraCon = new OracleConnection(oradbConString)) { oraCon.Open(); for (int index = 0; index < dataTable.Rows.Count; ++index) { using (OracleCommand comOra = oraCon.CreateCommand()) { // 增加BLOB字段content,替换为你实际的BLOB字段名,用参数化查询避免注入风险 comOra.CommandText = "select id,name,content,contenttype from blob_sample where id = :Id"; comOra.Parameters.Add("Id", dataTable.Rows[index]["id"]); using (OracleDataReader oracleDataReader = comOra.ExecuteReader()) { // 校验是否有查询结果再操作 if (oracleDataReader.Read()) { // content字段是索引2,对应BLOB字段,注意字段顺序要和查询语句一致 OracleBlob oracleBlob = oracleDataReader.GetOracleBlob(2); string fileName = oracleDataReader.GetString(1); // 取name字段作为文件名,可按需加后缀 string path = Path.Combine(tempDir, fileName); // FileStream用using包裹自动释放资源,不需要手动调用Close using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write)) { byte[] buffer = new byte[oracleBlob.Length]; int count = oracleBlob.Read(buffer, 0, Convert.ToInt32(oracleBlob.Length)); fileStream.Write(buffer, 0, count); } } } } } }
内容的提问来源于stack exchange,提问作者Didit Praditya
相关产品推荐
相关产品推荐

