none
如何 使用 ado 將資料寫回 DBF 檔 RRS feed

  • 問題

  • Hi :

    我有一個 dbf 檔案 使用 VB.NET 2005程式如下
    可以順利讀出 並且 加到 DATASET & DataGridView 中
    我隨便多加一筆資料 想寫回 原DBF檔
    卻有問題
    錯誤訊息如下
    """當傳遞擁有新資料列的 DataRow 集合時,更新需要有效的 InsertCommand。"""

    可以給我指導嗎

    謝謝 2006/11/25

    疑問:

    1.為何可以open 卻不能 Write DBF 檔案?
    2.oledb 不支援 DBF 檔? 或是 這個 DBF檔 根本不是 DBASE 格式??? 但是可以讀出欄位來@#$%^
    3.或是DBF格式有其他作法?或寫法?


    ===============================================================================
    Imports System.Data
    Imports System.Data.OleDb

    Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles Button1.Click

    Dim obj_OleDbConnection As OleDbConnection
    Dim obj_OleDbDataAdapter As OleDbDataAdapter
    Dim obj_OleDbCommand As OleDbCommand
    Dim obj_DataSet As New DataSet

    Dim str_OleDbConn As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source =C:\" _
    + ";Extended Properties=dBASE 5.0;"

    obj_OleDbConnection = New OleDbConnection(str_OleDbConn)
    obj_OleDbConnection.Open()

    Dim str_OleDbCommand As String = "select * from CUST.DBF"
    obj_OleDbCommand = New OleDbCommand(str_OleDbCommand, obj_OleDbConnection)

    obj_OleDbDataAdapter = New OleDbDataAdapter(str_OleDbCommand, obj_OleDbConnection)

    obj_OleDbDataAdapter.Fill(obj_DataSet, "CUST")
    DataGridView1.DataSource = obj_DataSet.Tables("CUST").DefaultView '加入的資料在此處可見

    Dim wrk_DbfRow As DataRow = obj_DataSet.Tables("CUST").NewRow

    wrk_DbfRow("CUSNO") = 1 '''隨便加入一行
    obj_DataSet.Tables("CUST").Rows.Add(wrk_DbfRow)

    obj_OleDbDataAdapter.Update(obj_DataSet, "CUST") ''' 死在此處?????!!!!

    obj_OleDbConnection.Close()

    End Sub


    End Class
    =============================================================================
    2006年11月25日 上午 01:46

解答

  • 看不懂你現在要幹麻...

    使用 CommandBuilder 就不需使用 Insert Command ,兩個是各有功能的互斥使用,是選擇一個來用。

    另外,dBase III/IV 的表格名稱為不含 .dbf 的部份,字串 A 要加引號。

    註:沒幫你測,調順序。

    CommandBuilder:

            obj_OleDbDataAdapter.Fill(obj_DataSet, 0)
            DataGridView1.DataSource = obj_DataSet.Tables(0).DefaultView

            Dim wrk_DbfRow As DataRow = obj_DataSet.Tables(0).NewRow

            wrk_DbfRow("CUSNO") = "A"
            obj_DataSet.Tables(0).Rows.Add(wrk_DbfRow)

            Dim obj_OleDbCommandBuilder As New OleDbCommandBuilder(obj_OleDbDataAdapter)

            obj_OleDbDataAdapter.Update(obj_DataSet, "0")

            obj_OleDbConnection.Close()

    InsertCommand:

    我自己用 selectCommand 來處理

      Dim myDataAdapter As New OleDbDataAdapter("insert into CUST (CUSNO) values ('A')", strProvider)
      myDataAdapter.SelectCommand.Connection.Open()
      nLine = myDataAdapter.SelectCommand.ExecuteNonQuery()
      myDataAdapter.SelectCommand.Connection.Close()
      myDataAdapter.Dispose()

      Return nLine

    2006年11月25日 上午 09:21
    版主

所有回覆

  • 你的 DataAdapter.InsertCommand 沒有給指令,Update() 有關新增的部份會失效 .
    同理,缺乏 DataAdapter.UpdateCommand 的話,Update() 有關修改的部份會失效 .
    缺乏 DataAdapter.DeleteCommand 的話,Update() 有關刪除的部份會失效 .

    2006年11月25日 上午 02:00
    版主
  • 關於 dBase 的檔案,建議你採用 Visual Foxpro Driver 來操控,在 MDAC 內建純 dBase III/IV 在功能上沒有 VFP 的 Driver 齊全。

    2006年11月25日 上午 02:14
    版主
  • 我之前對Visual Foxpro資料庫的操作都適用VFPOLEDB.1,這個你可以去微軟的網站找

    如果懶得手寫Command的話

    可以用CommandBuilder來做

    Dim obj_CommandBuilder As New OleDbCommandBuilder(obj_OleDbDataAdapter)

    加在obj_OleDbDataAdapter = New OleDbDataAdapter(str_OleDbCommand, obj_OleDbConnection)這行後面

    2006年11月25日 上午 04:16
  • 加上
    Dim obj_OleDbCommandBuilder As New OleDbCommandBuilder

    obj_OleDbCommandBuilder.DataAdapter = obj_OleDbDataAdapter

    以及

    'obj_OleDbDataAdapter.Update(obj_DataSet, "CUST") ''' 原先
    obj_OleDbCommandBuilder.DataAdapter.Update(obj_DataSet.Tables("CUST")) ''改寫

    是不是這樣改寫???

    但還是錯誤????!!!! error code as follow

    INSERT INTO 陳述式的語法錯誤。
    2006年11月25日 上午 05:37
  • Hi: 璉璉

    我是VB初 學者
    你給的提示太高深了

    讀DBF檔案
    是不是這樣的用法根本不對

    請再給一些方向 或參考範圍

    我只是幫人轉檔
    可能從一些 EXCEL 及 DBF 檔  轉至 MDB 或SQL
    使用  VB.NET 2005 coding

    非常謝謝  你的撥冗回覆

    可以的話
    請給我方向

    如何正確有效讀出  *.dbf 檔案
    並可 insert  update 回原檔案

    謝謝

    2006年11月25日 上午 05:48
  • 我看到你在我網誌上貼的回覆了。由於該主題為 In 子句的使用討論,您的文章與主題不符,恕刪除。

    你可能把 ado 的觀念帶入 ado.net 上,所以產生衝突矛盾。

    ado 是線上使用資料庫,所以隨時用 update 都沒有問題。

    ado.net 是離線使用資料庫,只有讀取、新增、更新、刪除瞬間會連線,而後者均是透過 SQL 語法來處理,與 ado 直接存取不同。

    所以 ado.net 並不會直接處理:obj_OleDbDataAdapter.Update(obj_DataSet, "CUST")

    因為 ado.net 是送新增語法給資料庫。所以你要新增時,可以自己編寫新增語法或是使用 OleDbCommandBuilder ,你可以參考線上手冊上的範例原始碼:

    http://msdn2.microsoft.com/zh-tw/library/system.data.oledb.oledbcommandbuilder(VS.80).aspx

    使用 OleDbCommandBuilder 時,你的資料表必須有主鍵值,若是你用 Excel 編輯 dbf ,不能設定主鍵值。

    用 Foxpro 的驅動程式去連的原因是,早期 dBase III/IV 的驅動程式不支援長檔名及中文檔名,還有只能讀取不能寫入的問題,而 Foxpro 是微軟的產品,使用 dbf 格式,且持續更新,所以這邊的驅動程式功能比較完整。

    我平常不存取 dBase III/IV 的格式,上面寫的是 ADO.NET 通則跟 dbf 存取經驗。

    2006年11月25日 上午 06:54
    版主
  • 非常謝謝
    我先試試看??!!! 慢慢釐清自己的觀念後
    如有問題
    再跟你請教

    網誌上貼的因為急著找答案
    所以未能察覺
    非常抱歉

    常拜讀你有關文章
    實受益斐淺

    再次致意
    2006年11月25日 上午 07:13
  • Hi: 大家好

    仍在奮鬥中..................@#$%!!!

    縱合大家意見
    改寫如下

    還是有問題

    簡單講
    我只是讀出 *.dbf檔 再寫入一筆資料
    在dataset 及 datagridview 中可見加入的資料

    但是程式執行完

    就是沒有加進去到 DBF 檔中

    煩請原諒初學者....

    謝謝



    Dim obj_OleDbConnection As OleDbConnection
            Dim obj_OleDbDataAdapter As OleDbDataAdapter
            Dim obj_OleDbCommand As OleDbCommand
            Dim obj_DataSet As New DataSet

            Dim str_OleDbConn As String = "Provider=vfpoledb.1;Data Source =C:\"
            obj_OleDbConnection = New OleDbConnection(str_OleDbConn)
            obj_OleDbConnection.Open()

            Dim str_OleDbCommand As String = "select * from CUST"
            obj_OleDbCommand = New OleDbCommand(str_OleDbCommand, obj_OleDbConnection)
            obj_OleDbDataAdapter = New OleDbDataAdapter(str_OleDbCommand, obj_OleDbConnection)

            Dim obj_OleDbCommandBuilder As New OleDbCommandBuilder(obj_OleDbDataAdapter)


            obj_OleDbDataAdapter.Fill(obj_DataSet, 0)
            DataGridView1.DataSource = obj_DataSet.Tables(0).DefaultView

            Dim wrk_DbfRow As DataRow = obj_DataSet.Tables(0).NewRow

            wrk_DbfRow("CUSNO") = "A"
            obj_DataSet.Tables(0).Rows.Add(wrk_DbfRow)

            Dim obj_insertCommande As OleDbCommand

            obj_insertCommande = New OleDbCommand("insert into CUST.dbf(CUSNO) values (A)", obj_OleDbConnection)
            obj_OleDbDataAdapter = New OleDbDataAdapter("insert into CUST(CUSNO) values (A)", obj_OleDbConnection)

            obj_OleDbDataAdapter.Update(obj_DataSet, "0")

            obj_OleDbConnection.Close()
    2006年11月25日 上午 09:05
  • 看不懂你現在要幹麻...

    使用 CommandBuilder 就不需使用 Insert Command ,兩個是各有功能的互斥使用,是選擇一個來用。

    另外,dBase III/IV 的表格名稱為不含 .dbf 的部份,字串 A 要加引號。

    註:沒幫你測,調順序。

    CommandBuilder:

            obj_OleDbDataAdapter.Fill(obj_DataSet, 0)
            DataGridView1.DataSource = obj_DataSet.Tables(0).DefaultView

            Dim wrk_DbfRow As DataRow = obj_DataSet.Tables(0).NewRow

            wrk_DbfRow("CUSNO") = "A"
            obj_DataSet.Tables(0).Rows.Add(wrk_DbfRow)

            Dim obj_OleDbCommandBuilder As New OleDbCommandBuilder(obj_OleDbDataAdapter)

            obj_OleDbDataAdapter.Update(obj_DataSet, "0")

            obj_OleDbConnection.Close()

    InsertCommand:

    我自己用 selectCommand 來處理

      Dim myDataAdapter As New OleDbDataAdapter("insert into CUST (CUSNO) values ('A')", strProvider)
      myDataAdapter.SelectCommand.Connection.Open()
      nLine = myDataAdapter.SelectCommand.ExecuteNonQuery()
      myDataAdapter.SelectCommand.Connection.Close()
      myDataAdapter.Dispose()

      Return nLine

    2006年11月25日 上午 09:21
    版主
  • hello:

    ok.終於可以了
    原先是我的觀念不夠清楚
    東拼西措的大雜燴
    最後終於是出來了

    小問題

    大傷腦筋

    非常謝謝各位


    結案了--------------------------------------------


    2006年11月25日 上午 11:04