从 SQL table 条记录创建 .DBF 文件

Create .DBF file from SQL table records

我想从 SQL table 条记录创建一个 .DBF 文件。

比如在SQL中有一个名为CountryMaster的table,它有5列:

  1. ID int identity(1,1)
  2. 名称 varchar(100)
  3. 详情 varchar(200)
  4. 状态位
  5. CreatedDate 日期时间

它有 100 行。

如何从 C# 中导出 .DBF 文件中 headers 的这些记录?

注意:创建的.DBF文件大小必须非常紧凑。

你可以看到 Xbase Data file (*.dbf) structure and write your own code but I have done the implementation and have been using it for years. Here you can find it on GitHub


如何使用图书馆

在名为 DbfFile.cs 的文件中有一些 write 方法。您可以使用其中任何一个。我将解释其中的一些:

第一种写法

DataTable 另存为 dbf 文件:

static void Write(string fileName, System.Data.DataTable table, Encoding encoding)
  • fileName:是您要保存 .dbf 输出文件的位置。
  • table:是您从 SQL 服务器 或任何其他来源读取的数据。
  • encoding: 保存字符串数据时使用的编码

第二种写法

List<T> 保存到 dbf 文件中。

static void Write<T>(string fileName,
                                    List<T> values,
                                    List<Func<T, object>> mapping,
                                    List<DbfFieldDescriptor> columns,
                                    Encoding encoding)

读取数据库并将结果保存到某些class类型中,然后使用此方法将class值保存到dbf文件中。这是它的参数说明:

  • fileName:要保存的dbf文件名
  • values:您的数据作为 T 类型的对象列表保存到 dbf 文件中
  • mapping:告诉此方法如何从 class 类型检索数据的函数列表。
  • columns: dbf 列信息
  • encoding: dbf文件的编码。

第二种写入方法的示例

由于第一种方法很简单,我为您提供了第二种写入方法的示例。假设您想将 List<MyClass> 数据保存到 dbf 文件中。这是代码

class MyClass
{
    public int Id {get;set;}
    public string Name {get;set;}
}

现在您可以像这样将 List<MyClass> 保存到 dbf 文件中:

var idColumn = DbfFieldDescriptors.GetIntegerField("Id");
var nameColumn = DbfFieldDescriptors.GetStringField("Name");
var columns = new List<DbfFieldDescriptor>() { idColumn, nameColumn };

Func<MyClass, object> mapId = myClass => myClass.Id;
Func<MyClass, object> mapName = myClass => myClass.Name;
var mapping = new List<Func<MyClass, object>>() { mapId, mapName };

List<MyClass> values = new List<MyClass>();
values.Add(new MyClass() { Id = 1, Name = "name1" });

DbfFileFormat.Write(@"C:\yourFile.dbf", values, mapping, columns, Encoding.ASCII);

Also using this library you can read dbf files and your code do not depend on Microsoft.Jet.OLEDB or anything else.

尽情享受吧。

您需要的大部分信息都可以在 Trouble with Insert Into .dbf file 中找到,因为它展示了如何创建 table 并在创建 .dbf 文件时向其中插入值。您将需要对您指定的字段进行一些修改,但是该页面描述了您需要的一切。

我愿意帮忙。但是,id 坚持使用 OLEDB 的普通过程用于 VPF。

创建 TABLE DBF

这可能是您为 .DBF

创建的 table 脚本
CREATE TABLE "C:\test.dbf" ([ID] Numeric(18,0), [Name] Char(100) NULL, [Details] Char(200) NULL, [Status] Logical NULL, [CreateDate] DATETIME NULL)

然后,您可以从 OLE DB 脚本中调用它,如下所示。

    string vpfScript = "CREATE TABLE \"C:\test.dbf\" ([ID] Numeric(18,0), [Name] Char(100) NULL, [Details] Char(200) NULL, [Status] Logical NULL, [CreateDate] DATETIME NULL)";
    string connectionString = @"Provider=VFPOLEDB.1;Data Source=C:\test.dbf";
    OleDbConnection connection = new OleDbConnection(connectionString);

    using (OleDbCommand scriptCommand = connection.CreateCommand())
    {
         connection.Open();
         scriptCommand.CommandType = CommandType.StoredProcedure;
         scriptCommand.CommandText = "ExecScript";
         scriptCommand.Parameters.Add("myScript", OleDbType.Char).Value = vfpScript;
         scriptCommand.ExecuteNonQuery();
    }

在 TABLE

中导入行

要在 DBF table 中导入行,它不如我们在其他数据库中使用的通常 SQL 脚本那么远。

    string vpfScript = "INSERT INTO \"C:\test.dbf\" ([ID], [Name], [Details], [Status], [CreateDate]) VALUES (1,'test john','test details',.t.,{^2015-09-15)";
    string connectionString = @"Provider=VFPOLEDB.1;Data Source=C:\test.dbf";
    OleDbConnection connection = new OleDbConnection(connectionString);

    using (OleDbCommand scriptCommand = connection.CreateCommand())
    {
        connection.Open();
        scriptCommand.CommandType = CommandType.StoredProcedure;
        scriptCommand.CommandText = "ExecScript";
        scriptCommand.Parameters.Add("myScript", OleDbType.Char).Value = vfpScript;
        scriptCommand.ExecuteNonQuery();
    }

您现在可以根据需要更改值,就像下面的用法一样。

    DataTable dt = new DataTable(); // assuming this is already populated from your SQL Database.
    StringBuilder buildInsert = new StringBuilder();
    string connectionString = @"Provider=VFPOLEDB.1;Data Source=C:\test.dbf";
    OleDbConnection connection = new OleDbConnection(connectionString);

    using (OleDbCommand scriptCommand = connection.CreateCommand())
    {
         connection.Open();

         foreach(DataRow dr in dt.Rows)
         {
             string id = dr["ID"].ToString();
             string name = dr["Name"].ToString();
             string details = dr["Details"].ToString();
             string status = Convert.ToBoolean(dr["Status"]) ? ".t." : ".f.";
             string createDate = "{^" + Convert.ToDateTime(dr["CreateDate"]).ToString("yyyy-MM-dd") + "}";
             builderInsert.Append("INSERT INTO \"C:\test.dbf\" ([ID], [Name], [Details], [Status], [CreateDate]) VALUES (" + id + ",\"" + name + "\",\"" + details + "\"," + status + "," + createDate + ")" + Environment.NewLine);

             scriptCommand.CommandType = CommandType.StoredProcedure;
             scriptCommand.CommandText = "ExecScript";
             scriptCommand.Parameters.Add("myScript", OleDbType.Char).Value = builderInsert;
             scriptCommand.ExecuteNonQuery();
             builderInsert = "";
          }
     }

如果您有其他疑虑,请告诉我。 不要忘记在你的机器上安装这个。 VFP OLE DB

要为您提供 C# 解决方案,我首先要下载 Microsoft Visual Foxpro OleDb Provider,它适用于 .DBF 表。

在 C# 代码的顶部,添加

using System.Data.SqlClient;
using System.Data.OleDb;

然后,在一个方法中移动数据

    void MoveFromSQLToDBF()
    {    
        // have a table to pull down your SQL Data...
        var dataFromSQL = new DataTable();

        // However your connection to your SQL-Server
        using (var sqlConn = new  SqlConnection("YourSQLConnectionString"))
        {
           using (var sqlCmd = new SqlCommand("", sqlConn))
           {
              // Get all records from your table
              sqlCmd.CommandText = "select * from CountryMaster";
              sqlConn.Open();
              var sqlDA = new SqlDataAdapter();
              // populate into a temp C# table
              sqlDA.Fill(dataFromSQL);
              sqlConn.Close();
           }
        }

        // Now, create a connection to VFP 
        // connect to a PATH where you want the data.
        using (var vfpConn = new OleDbConnection(@"Provider=VFPOLEDB.1;Data Source=C:\SomePathOnYourMachine\"))
        {
           using (var vfpCmd = new OleDbCommand("", vfpConn))
           {
              // Create table command for VFP
              vfpCmd.CommandText = "CREATE TABLE testFromSQL ( ID Numeric(18,0), [Name] Char(100) NULL, [Details] Char(200) NULL, [Status] Logical NULL, [CreateDate] DATETIME NULL)";

              vfpConn.Open();
              vfpCmd.ExecuteNonQuery();

              // Now, change the command to a SQL-Insert command, but PARAMETERIZE IT.
              // "?" is a place-holder for the data
              vfpCmd.CommandText = "insert into testFromSQL "
                 + "( ID, [Name], [Details], [Status], [CreateDate]) values ( ?, ?, ?, ?, ? )";

              // Parameters added in order of the INSERT command above.. 
              // SAMPLE values just to establish a basis of the column types
              vfpCmd.Parameters.Add( new OleDbParameter( "parmID", 10000000 ));
              vfpCmd.Parameters.Add( new OleDbParameter( "parmName", "sample string" ));
              vfpCmd.Parameters.Add(new OleDbParameter( "parmDetails", "sample string" ));
              vfpCmd.Parameters.Add(new OleDbParameter( "parmStatus", "sample string" ));
              vfpCmd.Parameters.Add( new OleDbParameter( "parmCreateDate", DateTime.Now ));

              // Now, for each row in the ORIGINAL SQL table, apply the insert to VFP
              foreach (DataRow dr in dataFromSQL.Rows)
              {
                 // set the parameters based on whatever current record is
                 vfpCmd.Parameters[0].Value = dr["ID"];
                 vfpCmd.Parameters[1].Value = dr["Name"];
                 vfpCmd.Parameters[2].Value = dr["Details"];
                 vfpCmd.Parameters[3].Value = dr["Status"];
                 vfpCmd.Parameters[4].Value = dr["CreateDate"];
                 // execute it
                 vfpCmd.ExecuteNonQuery();
              }

              // Finally, for compactness, use a VFP Script to copy to Excel (CSV) format
              using (var vfpCmd2 = new OleDbCommand("", vfpConn))
              {
                 vfpCmd2.CommandType = CommandType.StoredProcedure;
                 vfpCmd2.CommandText = "ExecScript";

                 vfpCmd2.Parameters.Add(new OleDbParameter( "csvScript", 
@"Use testFromSQL
copy to YourCompactFile.csv type csv
use" ));

                 vfpCmd2.ExecuteNonQuery();
              }

              // close VFP connection
              vfpConn.Close();

           }
        }
    }

由于OleDb不支持copy TYPE CSV,我为你找到了this post on S/O to dump into CSV format