2008年6月17日 星期二

C# 使用 ADOX 建立新 Table

有時,需要把資料匯出到 MDB 裡面,但是在 ADO.Net 中沒有建立 MDB 以及在 MDB 中建立 Table 的功能 (create table 的 SQL 敘述除外)。
所以,有必要撰寫這樣的工具程式,以便於後續方便使用

使用 ADO 以及 ADOX 之前,要加入兩個 COM 的參考
  1. C:\Program Files\Common Files\System\ado\msado15.dll (ADODB)
  2. C:\Program Files\Common Files\System\ado\msadox.dll (ADOX)
這兩個 COM 加進來之後,命名空間如括弧內所示
接下來,撰寫程式如下

/// <summary>
/// 建立 MDB 資料庫以及資料表
/// </summary>
public class MDBCreate
{
  private ADOX.CatalogClass catalog = new ADOX.CatalogClass();
  private ADODB.Connection connection = new ADODB.ConnectionClass();
  private string createConnStr =
    "Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0}";
  private string _fileName = "";

  /// <summary>
  /// MDB 檔案名稱
  /// </summary>
  public string FileName
  {
    get
    {
      return _fileName;
    }
    set
    {
      _fileName = value;

    }
  }

  /// <summary>
  /// 建立新的 MDB 資料庫
  /// </summary>
  /// <param name="deleteIfExist">是否刪除現有的</param>
  /// <returns>是否建立成功</returns>
  public bool CreateMDB(bool deleteIfExist)
  {
    try
    {
      if (deleteIfExist)
      {
        if (File.Exists(_fileName))
          File.Delete(_fileName);
      }
      catalog.Create(String.Format(createConnStr, _fileName));
      return true;
    }
    catch
    {
      return false;
    }
  }

  /// <summary>
  /// 利用 DataTable 結構,於 MDB 檔案中建立新的 Table
  /// </summary>
  /// <param name="tableName">Table 名稱</param>
  /// <param name="sourceTable">包含表格結構的 DataTable 執行個體</param>
  /// <returns>是否建立成功</returns>
  public bool CreateTable(string tableName, DataTable sourceTable)
  {
    string connStr = String.Format(createConnStr, _fileName) + ";Persist Security Info=False";
    connection.Open(connStr, "", "", 0);
    catalog.ActiveConnection = connection;

    ADOX.TableClass table = new TableClass();
    ADOX.DataTypeEnum fieldType = ADOX.DataTypeEnum.adWChar;
    int fieldLength = 0;

    table.Name = tableName;

    for (int i = 0; i < sourceTable.Columns.Count; i++)
    {
      DataColumn column = sourceTable.Columns[i];

      switch (column.DataType.FullName)
      {
        case "System.Boolean":
          fieldType = ADOX.DataTypeEnum.adBoolean;
          break;
        case "System.Byte":
          fieldType = ADOX.DataTypeEnum.adUnsignedTinyInt;
          break;
        case "System.Char":
          fieldType = ADOX.DataTypeEnum.adWChar;
          fieldLength = column.MaxLength;
          if (fieldLength == -1)
            fieldLength = 255;
          break;
        case "System.DateTime":
          fieldType = ADOX.DataTypeEnum.adDate;
          break;
        case "System.Decimal":
          fieldType = ADOX.DataTypeEnum.adCurrency;
          break;
        case "System.Double":
          fieldType = ADOX.DataTypeEnum.adDouble;
          break;
        case "System.Int16":
          fieldType = ADOX.DataTypeEnum.adSmallInt;
          break;
        case "System.Int32":
          fieldType = ADOX.DataTypeEnum.adInteger;
          break;
        case "System.Int64":
          fieldType = ADOX.DataTypeEnum.adInteger;
          break;
        case "System.SByte":
          fieldType = ADOX.DataTypeEnum.adSmallInt;
          break;
        case "System.Single":
          fieldType = ADOX.DataTypeEnum.adSingle;
          break;
        case "System.String":
          // 因為 MDB 檔的文字欄位最大長度是 255
          // 所以超過時,以 memo 欄位存放
          if (column.MaxLength > 255)
          {
            fieldType = ADOX.DataTypeEnum.adLongVarWChar;
            fieldLength = 0;
          }
          else
          {
            fieldType = ADOX.DataTypeEnum.adVarWChar;
            fieldLength = column.MaxLength;
            if (fieldLength == -1)
              fieldLength = 255;
          }
          break;
        case "System.UInt16":
          fieldType = ADOX.DataTypeEnum.adSmallInt;
          break;
        case "System.UInt32":
          fieldType = ADOX.DataTypeEnum.adInteger;
          break;
        case "System.UInt64":
          fieldType = ADOX.DataTypeEnum.adInteger;
          break;
        case "System.Byte[]":
          fieldType = ADOX.DataTypeEnum.adLongVarBinary;
          break;
      }

      // 將新增的欄位物件加入 Table 中,並設定欄位屬性為可 null
      table.Columns.Append(column.ColumnName, fieldType, fieldLength);
      table.Columns[i].Attributes = ColumnAttributesEnum.adColNullable;
    }

    try
    {
      // 將新增的 Table 物件加入 Catalog 物件,以達到建立新 Table 的目的
      catalog.Tables.Append(table);
      catalog.ActiveConnection = null;
      return true;
    }
    catch
    {
      return false;
    }
    finally
    {
      connection.Close();
    }
  }
}

沒有留言: