【问题标题】:How can I save a DataTable to a .DBF?如何将 DataTable 保存到 .DBF?
【发布时间】:2010-09-24 06:44:07
【问题描述】:

我一直在编写一个程序来读取 dbf 文件,处理数据并将其保存回 dbf。我遇到的问题与写作部分有关。

    private const string constring = "Driver={Microsoft dBASE Driver (*.dbf)};"
                                   + "SourceType=DBF;"
                                   + "DriverID=277;"
                                   + "Data Source=¿;"
                                   + "Extended Properties=dBASE IV;";
    private const string qrystring = "SELECT * FROM [¿]";
    public static DataTable loadDBF(string location)
    {
        string filename = ConvertLongPathToShort(Path.GetFileName(location));
        DataTable table = new DataTable();
        using(OdbcConnection conn = new OdbcConnection(RTN(constring, filename)))
        {
            conn.Open();
            table.Load(new OdbcCommand(RTN(qrystring, filename), conn).ExecuteReader());
            conn.Close();
        }
        return table;
    }

    private static string RTN(string stmt, string tablename)
    { return stmt.Replace("¿", tablename); }

    [DllImport("Kernel32", CharSet = CharSet.Auto)]
    static extern Int32 GetShortPathName(
    String path,                // input string
    StringBuilder shortPath,    // output string
    Int32 shortPathLength);     // StringBuilder.Capacity

    public static string ConvertLongPathToShort(string longPathName)
    {
        StringBuilder shortNameBuffer;
        int size;

        shortNameBuffer = new StringBuilder();

        size = GetShortPathName(longPathName, shortNameBuffer, shortNameBuffer.Capacity);
        if (size >= shortNameBuffer.Capacity)
        {
            shortNameBuffer.Capacity = size + 1;
            GetShortPathName(longPathName, shortNameBuffer, shortNameBuffer.Capacity);
        }

        return shortNameBuffer.ToString();
    }

这就是我正在使用的。我已经尝试了多种方法来编写一个新文件,但都没有成效。老实说,虽然通常我会提倡形式和功能,但我只是想让该死的东西发挥作用,这个应用程序应该做一件非常具体的事情,它不会模拟天气。

-=# 编辑#=-

由于时间压力,我已经停止使用该应用程序,但在我放弃它之前,我意识到我正在使用的特定格式的 dbf 没有主键信息。这当然意味着我必须从本质上将数据读取到 DataTable,弄乱它,然后擦除 dbf 中的所有记录并从头开始插入所有内容。 开玩笑吧。

【问题讨论】:

    标签: c# odbc dbf


    【解决方案1】:

    对于未来来到这里的人:我今天写了这个,效果很好。文件名没有扩展名 (.dbf)。路径(用于连接)只是目录路径(无文件)。您可以将数据表添加到数据集并传入。此外,我的一些数据类型是 foxpro 数据类型,可能与所有 DBF 文件不兼容。希望这会有所帮助。

        public static void DataSetIntoDBF(string fileName, DataSet dataSet)
        {
            ArrayList list = new ArrayList();
    
            if (File.Exists(Path + fileName + ".dbf"))
            {
                File.Delete(Path + fileName + ".dbf");
            }
    
            string createSql = "create table " + fileName + " (";
    
            foreach (DataColumn dc in dataSet.Tables[0].Columns)
            {
                string fieldName = dc.ColumnName;
    
                string type = dc.DataType.ToString();
    
                switch (type)
                {
                    case "System.String":
                        type = "varchar(100)";
                        break;
    
                    case "System.Boolean":
                        type = "varchar(10)";
                        break;
    
                    case "System.Int32":
                        type = "int";
                        break;
    
                    case "System.Double":
                        type = "Double";
                        break;
    
                    case "System.DateTime":
                        type = "TimeStamp";
                        break;
                }
    
                createSql = createSql + "[" + fieldName + "]" + " " + type + ",";
    
                list.Add(fieldName);
            }
    
            createSql = createSql.Substring(0, createSql.Length - 1) + ")";
    
            OleDbConnection con = new OleDbConnection(GetConnection(Path));
    
            OleDbCommand cmd = new OleDbCommand();
    
            cmd.Connection = con;
    
            con.Open();
    
            cmd.CommandText = createSql;
    
            cmd.ExecuteNonQuery();
    
            foreach (DataRow row in dataSet.Tables[0].Rows)
            {
                string insertSql = "insert into " + fileName + " values(";
    
                for (int i = 0; i < list.Count; i++)
                {
                    insertSql = insertSql + "'" + ReplaceEscape(row[list[i].ToString()].ToString()) + "',";
                }
    
                insertSql = insertSql.Substring(0, insertSql.Length - 1) + ")";
    
                cmd.CommandText = insertSql;
    
                cmd.ExecuteNonQuery();
            }
    
            con.Close();
        }
    
        private static string GetConnection(string path)
        {
            return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + path + ";Extended Properties=dBASE IV;";
        }
    
        public static string ReplaceEscape(string str)
        {
            str = str.Replace("'", "''");
            return str;
        }
    

    【讨论】:

    • 我在 System.Decimal 中添加了大小写,但它对您的代码有所帮助谢谢
    • insert 语句运行时出现异常Data type mismatch in criteria expression.。知道是什么原因造成的吗?
    • 我想通了。您的代码没有检查 DataSet 中的 DBNull 值,而是在应该插入 NULL 的列中插入一个空字符串 ''
    【解决方案2】:

    使用 ADO.Net 读取和写入 dbf 文件非常慢,因此我建议您使用另一种方法。

    一种选择是使用旧的 DAO 3.6 库。这要快得多并且兼容,但取决于 com 对象的工作。

    更好的方法是使用开源DBFExporter component。它可能需要一些代码来设置(您需要一个具有描述您的记录集的属性的类,并且这些属性必须具有某些属性集),但之后它工作得非常好。它使用起来很快,但它不读取 dbf 文件。该组件是 LGPL 下的许可证,因此您应该能够在商业代码中使用它。

    【讨论】:

      【解决方案3】:

      您使用的是哪种 dbf 文件? (有几个,例如 dBase、FoxPro 等不是 100% 兼容的。)我已经让这个与 C# 中的 Microsoft Visual FoxPro OleDB Provider 一起工作,你可能会试一试,而不是使用 dBase ODBC 驱动程序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-20
        • 2011-06-11
        • 1970-01-01
        • 2019-06-20
        • 2016-06-11
        • 2011-09-02
        相关资源
        最近更新 更多