由于种种原因,需要将某些数据以dbf的形式导出,网上苦寻资料,走了许多弯路;
首先记录下走的弯路
1.DBF字段名称长度限制
在编程过程中老是报一些奇怪的错误,创建表格的sql语句拿到sql数据库中跑完全没有问题,但是数据库中老是报各种奇怪的错误,比如建表语句:
create table 表格(公司本年度总收入 int,公司本年度总支出 int)
在程序中执行这段语句总是会出现错误:“公司本年度”已经存在于表中,百思不得其解;
后来经过查资料,各种死磕,最后发现所有成功导出的dbf文件中所有字段都不超过5个汉字,10个英文字符,这是dbf毫无人性的地方,字段定义不能超过10个字节,如果超过则自动截取,运气好截取的前五个字没有重复就成功导出,脸黑的就。。。
2.DBF字段类型
目前真没有找到DBF字段类型官方详细的介绍,我只能说说我当前用过的有varchar,int,double,char,numeric,至于长度什么的,这个自己下个fvp玩玩就知道了;
废话少说,直接上代码
public class DbfExportHelper { /// <summary> /// 数据库所在路径 /// </summary> private string filePath = ""; /// <summary> /// 连接字符串 /// </summary> private string connstring = ""; /// <summary> /// 数据库连接 /// </summary> private OleDbConnection Connection = new OleDbConnection(); /// <summary> /// 错误信息 /// </summary> private string _ErrInfo; /// <summary> /// 构造函数 /// </summary> /// <param name="filePath">dbf文件所在文件夹路径</param> public DbfExportHelper(string filePath) { this.filePath = filePath; this.connstring = string.Format("Provider = Microsoft.Jet.OLEDB.4.0 ;Data Source ={0};Extended Properties=dBASE IV;", filePath); this.Connection = new OleDbConnection(connstring); } /// <summary> /// 改变数据库所在路径 /// </summary> /// <param name="filePath">新文件夹路径</param> /// <returns></returns> public bool ChangeDbfPosition(string filePath) { bool success = true; if (!Directory.Exists(filePath)) { success = false; } else { this.filePath = filePath; this.connstring = string.Format("Provider = Microsoft.Jet.OLEDB.4.0 ;Data Source ={0};Extended Properties=dBASE IV;", filePath); this.Connection = new OleDbConnection(connstring); this._ErrInfo = string.Empty; } return success; } /// <summary> /// 构造dbf文件,文件名称为dt的表名,后缀名为dbf /// </summary> /// <param name="dt">待写入的表格数据</param> /// <returns></returns> public bool CreateNewTable(DataTable dt){ bool success = false; OleDbCommand command = Connection.CreateCommand(); try { if(File.Exists(filePath +@"\"+dt.TableName+".dbf")) { File.Delete(filePath + @"\" + dt.TableName + ".dbf"); } Connection.Open(); command.CommandType = CommandType.Text; List<string> cols = new List<string>(); foreach(DataColumn dc in dt.Columns) { string colType = ""; string colName = dc.ColumnName; switch (dc.DataType.Name) { case "Boolean": colType = "bool"; break; case "Double": case "Float": colType = "double"; break; case "Int16": case "Int32": case "Int64": case "Int": colType = "int"; break; case "String": colType = "varchar"; break; default: colType = "varchar"; break; } cols.Add(string.Format(@"{0} {1}",colName,colType)); } string cols_where = string.Join(",", cols); string sql = string.Format(@"CREATE TABLE {0} ({1})", dt.TableName,cols_where); command.CommandText = sql; //"CREATE TABLE table1 (自动编号 int,名称 Char(5),工资 Double)"; command.ExecuteNonQuery(); success = true; } catch (Exception c) { _ErrInfo = c.Message; } finally { command.Dispose(); if (Connection.State == System.Data.ConnectionState.Open) Connection.Close(); command.Dispose(); } return success; } /// <summary> /// 导入数据到dbf文件 /// </summary> /// <param name="dt"></param> /// <returns>导入的数据条数</returns> public int fillData(DataTable dt) { int count = 0; OleDbCommand dc = Connection.CreateCommand(); _ErrInfo = ""; try { Connection.Open(); //导入数据 foreach (DataRow row in dt.Rows) { string sqlInsert = "insert into " + dt.TableName + "({0}) values({1})"; string invalues = ""; string cols = ""; foreach (DataColumn col in dt.Columns) { if (row[col].ToString() != string.Empty && row[col].ToString() != null && row[col].ToString() != "null") { cols += col.ColumnName + ","; if (col.DataType == typeof(string)) { invalues += "'" + row[col].ToString() + "',"; } else { invalues += row[col].ToString() + ","; } } } invalues = invalues.Remove(invalues.Length - 1, 1); cols = cols.Remove(cols.Length - 1, 1); sqlInsert = string.Format(sqlInsert, cols,invalues); dc.CommandText = sqlInsert; count+= dc.ExecuteNonQuery(); } } catch (Exception err) { _ErrInfo = err.Message; } finally { if (Connection != null) Connection.Close(); dc.Dispose(); } return count; } /// <summary> /// 摧毁对象 /// </summary> public void Dispose() { if (Connection != null) Connection.Dispose(); }
}
这里使用的是Microsoft.Jet.OLEDB.4.0这个驱动,Microsoft.Jet.OLEDB.4.0是一种ACCESS数据库的搜索引擎,但是好像没有装access的电脑上也能用,
自己写了个测试代码:
DataTable dt = new DataTable();// 这里是取数据的步骤, dt.TableName = "ceshi";// 必须有表名 DbfExportHelper helper = new DbfExportHelper(@"E:\download"); helper.CreateNewTable(dt); helper.fillData(dt);
注意:
如果是web后台的方法,当部署在iis上可能无法生成dbf,错误代码为0x80070002;
解决方法:
1.打开iis管理器,选择应用程序池
2.选择建站使用的程序池,我这里选择的是.net 4.0,右键选择高级设置
3.将启用32位应用程序改为True即可