OleDbDataAdapter说明

本文介绍了如何从LINQ转换到更基础的ADO.NET数据库连接方法,具体涉及到OleDbConnection、OleDbDataAdapter以及如何将数据填充到DataTable中,并通过实例展示了如何操作数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近用到了C#得数据库,虽然一开始学的是linq但是现在决定还是掌握更为基础的ADO.NET 数据库连接方法

1) OleDbDataAdapter

 

           OleDbConnection Connector = new OleDbConnection(StrConnect);//建立连接
            Connector.Open();           
           string SELECT_DATA = "SELECT * FROM [" + Tb_Data + "]";
            OleDbDataAdapter Da = new OleDbDataAdapter(SELECT_DATA, Connector);
            DataTable TableTemp = new DataTable();//
            Da.Fill(TableTemp);//将OleDbDataAdapter 填充到DataTable数据表中,然后对DataTable进行操作
            _nFeatureNumber = TableTemp.Rows.Count;
            Features = new Feature[_nFeatureNumber];
            int ifeature = 0;
            foreach (DataRow row in TableTemp.Rows)
            {
                Features[ifeature] = new Feature();
                Features[ifeature].IsDigit = (bool)row["IsDigit"];
                Features[ifeature].Name = (string)row["FeatureName"];
                Features[ifeature].FeatureLevel = (int)row["FeatureLevel"];
                if (!Features[ifeature].IsDigit && row["Choises"] != null)
                    Features[ifeature].SetNominalValues((string)row["Choises"]);
                ++ifeature;
            }
            Da.Dispose();



 

<think>我们正在优化一个使用OleDbDataAdapter从Excel或Access数据库获取数据表的方法。目标是确保资源安全(无泄漏)和性能优化。 根据引用[1]中的代码片段,我们有一个名为GetExcelTableData的方法,它返回一个DataTable。我们注意到原始代码中可能没有正确处理资源(如OleDbConnection, OleDbDataAdapter)。 同时,引用[2]提到了一个封装数据库操作类的示例,其中使用了条件编译来支持多种数据库(但这里我们只关注OleDB)。引用[3]和[4]提供了连接Access数据库的参考。 优化重点: 1. 使用using语句确保所有实现IDisposable的对象(如OleDbConnection, OleDbDataAdapter)被正确释放。 2. 避免在循环中创建连接,尽量复用连接(但注意连接池机制,OleDB默认有连接池)。 3. 异常处理,记录详细的错误信息。 4. 考虑性能:比如只读取需要的列,但这里我们只是获取整个表,所以暂时不涉及。 原始方法(引用[1])的优化版本: 假设原始方法如下(根据引用[1]的片段): public DataTable GetExcelTableData(string path) { string tname = string.Empty; DataTable dt = new DataTable(); // ... 省略的代码:使用OleDbConnection和OleDbDataAdapter填充dt return dt; } 我们重构它,确保资源安全。 注意:连接字符串的构建在引用[3]和[4]中有示例,但这里我们假设调用者传入的path是Excel文件路径,连接字符串需要根据Excel版本构建(这里我们使用一个通用的方法构建连接字符串,但为了简化,我们假设调用者已经处理好连接字符串?或者我们根据path构建?) 但是,引用[1]中方法名为GetExcelTableData,所以path应该是Excel文件路径。我们需要构建连接字符串。 根据引用[4]中的参考,连接Excel的连接字符串可以这样写: string connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties='Excel 12.0;HDR=YES;IMEX=1'"; 但是,我们也要考虑不同版本的Excel(比如.xls和.xlsx)?或者使用统一的连接字符串?这里我们假设使用ACE.OLEDB.12.0(可以同时读取xls和xlsx)。 另外,我们需要获取表名。在Excel中,每个工作表就是一个表。我们可以通过获取架构信息来得到第一个表,或者由调用者指定表名?原始方法中没有指定表名,所以我们需要获取第一个表。 步骤: 1. 构建连接字符串。 2. 打开连接,获取所有表名(这里我们取第一个表)。 3. 使用OleDbDataAdapter填充DataTable。 优化后的代码:</think>### 优化后的 GetDataTable 方法(OleDB 资源安全版) ```csharp public DataTable GetDataTable(string tableName, string connectionString) { DataTable resultTable = new DataTable(); // 使用嵌套 using 确保资源释放 using (var dbConn = new OleDbConnection(connectionString)) using (var adapter = new OleDbDataAdapter()) { try { dbConn.Open(); // 优化查询:只获取必要数据 adapter.SelectCommand = new OleDbCommand( $"SELECT * FROM [{tableName}]", dbConn ); // 设置命令超时(避免长时间阻塞) adapter.SelectCommand.CommandTimeout = 30; // 填充数据表(指定范围避免内存溢出) adapter.Fill(0, 1000, resultTable); // 每次最多取1000行 } catch (OleDbException ex) { // 记录详细错误信息 LogError($"数据库错误[表:{tableName}]: {ex.ErrorCode}-{ex.Message}\n{ex.StackTrace}"); resultTable = null; } catch (Exception ex) { LogError($"系统错误: {ex.GetType().Name}\n{ex.Message}\n{ex.StackTrace}"); resultTable = null; } } return resultTable; } ``` ### 关键优化点说明 1. **资源安全保障** - 嵌套 `using` 语句确保连接(`OleDbConnection`)和适配器(`OleDbDataAdapter`)自动释放 - 符合 `IDisposable` 模式,避免连接池耗尽[^1] - 编译后等价于 `try/finally{Dispose()}` 结构 2. **内存管理优化** ```csharp adapter.Fill(0, 1000, resultTable); // 分页加载 ``` - 限制单次加载行数(避免大数据集内存溢出) - 支持后续扩展分页加载机制 - 大数据集建议配合 `DataTable.Clear()` 及时释放内存 3. **性能提升** - 设置 `CommandTimeout=30` 防止查询阻塞 - 显式指定表名 `[{tableName}]` 避免歧义 - 使用参数化查询防止 SQL 注入(示例见相关问题 4) 4. **异常处理增强** - 区分数据库异常(`OleDbException`)和系统异常 - 记录完整错误上下文(表名、错误码、堆栈) - 错误时返回 `null` 避免操作损坏数据 ### 连接字符串最佳实践 ```csharp // Access 连接字符串示例[^3] string accessConnStr = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Data\MyDB.accdb; Persist Security Info=False"; // Excel 连接字符串示例[^4] string excelConnStr = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Reports\Sales.xlsx; Extended Properties='Excel 12.0;HDR=YES'"; ``` ### 统一日志方法 ```csharp private void LogError(string message) { string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"); Directory.CreateDirectory(logDir); string logFile = Path.Combine(logDir, $"DB_Error_{DateTime.Now:yyyyMMdd}.log"); File.AppendAllText(logFile, $"[{DateTime.Now:HH:mm:ss.fff}] {message}\n" + new string('-', 80) + "\n"); } ``` > **性能提示**:对于超过 10,000 行的数据集,建议实现分页加载: > ```csharp > int pageSize = 1000; > for (int startIndex = 0; ; startIndex += pageSize) > { > DataTable page = new DataTable(); > adapter.Fill(startIndex, pageSize, page); > if (page.Rows.Count == 0) break; > // 处理当前页数据 > page.Clear(); // 及时释放内存 > } > ``` ### 相关问题 1. **如何实现 OleDB 连接池的性能优化?** 连接池默认启用,可通过连接字符串参数调整: `OleDb Services=-4;` (禁用连接池) `Max Pool Size=100;` (设置最大连接数)[^2] 2. **如何处理 Excel 数据中的混合数据类型?** 在连接字符串添加 `IMEX=1`: `Extended Properties='Excel 12.0;HDR=YES;IMEX=1'` 强制将混合列读为文本[^4] 3. **大数据集场景下如何避免内存溢出?** - 使用 `DataReader` 替代 `DataAdapter` - 分页加载(如上所示) - 设置 `DataTable.RemotingFormat = SerializationFormat.Binary` 4. **如何防止 SQL 注入攻击?** 使用参数化查询: ```csharp var cmd = new OleDbCommand( "SELECT * FROM Users WHERE Name = ?", dbConn ); cmd.Parameters.AddWithValue("p1", userName); ``` 5. **如何获取数据库元数据(表结构/列信息)?** 使用 `GetOleDbSchemaTable`: ```csharp var schema = dbConn.GetOleDbSchemaTable( OleDbSchemaGuid.Columns, new object[] { null, null, tableName } ); ``` > 参考实践:微软官方推荐在 `Fill` 方法中指定记录范围管理大数据集[^1],ACE.OLEDB 12.0 提供最优的 Excel/Access 兼容性[^3][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值