5

私が取り組んでいる私のプロジェクトはほぼ終了しました。.MDB ファイルを読み込んで、DataGrid にコンテンツを表示し、DataGrid でこれらの変更を取得して .MDB ファイルに保存しようとしています。また、ある .MDB ファイルからテーブルを取得して別の .MDB ファイルに保存できる関数も作成します。もちろん、変更を .MDB ファイルに保存する方法がわからない場合は、これを行うことはできません。

Google を広範囲に調査しましたが、私の質問に対する回答はありません。私は自分自身をこの特定のトピックの初心者だと考えているので、答えを複雑にしすぎないでください - .MDB ファイルを編集する最も簡単な方法が必要です! プログラミング例を教えてください。

  1. 既に DataGrid への接続を確立しているとします。Datagrid によって行われた変更を取得するにはどうすればよいですか? これは答えるのに十分簡単だと確信しています。
  2. 次に、このデータテーブルを取得し、元のデータセットに挿入し、そのデータセットを取得して .MDB ファイルを書き換える方法を知る必要があります。(変更されたテーブルのみを挿入する方法があれば、それをお勧めします。)

事前に感謝します。さらに情報が必要な場合はお知らせください。これはおそらく、このトピックについて私が尋ねなければならない最後のことです...神に感謝します.

編集:

私が使用している .mdb は、Microsoft Access データベースです。(複数の .mdb ファイルがあることさえ知りませんでした)

streamwriter などを使用して .MDB ファイルに直接書き込めないことはわかっていますが、DataSet 情報が既に含まれている .MDB ファイルを生成する方法はありますか? または、既に DataGrid にロードした .MDB ファイルにテーブルを追加する方法があります。方法があるはずです!

繰り返しますが、C# でプログラム的にこれを行う方法が必要です。

編集:

私のプロジェクトはかなり大きいですが、別のクラス ファイルを使用してすべてのデータベース接続を処理しています。私のデザインとソースが本当にずさんであることはわかっていますが、それで仕事は完了します。私は、インターネットで見つけた例と同じくらい上手です。

ここでは、別の形式で DataGrid に接続しているだけであることを思い出してください。Datagrid フォームから私のコードが必要な場合はお知らせください (ただし、なぜそれが必要なのかはわかりません)。DatabaseHandling.cs は、2 つの .MDB ファイルを処理します。そのため、そこに 2 つのデータセットが表示されます。最終的にこれを使用して、あるデータセットからテーブルを取得し、それらを別のデータセットに配置します。これらの値を .MDB ファイルに保存する方法を理解する必要があります。

とにかくこれを行うことはありますか?方法があるはずです...

編集:

私が調査して読んだことから...答えは私の目の前にあると思います。「Update()」コマンドを使用します。これは、実際にはこれを行う簡単な方法があることを再確認していますが、この更新コマンドの使用方法がまったくわからないという問題が残っています。

おそらく、次のように設定できます。

Oledb.OledbConnection cn = new Oledb.OledbConnection(); 
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Staff.mdb"; 
Oledb.OledbCommand cmd = new Oledb.OledbCommand(cn); 
cmd.CommandText = "INSERT INTO Customers (FirstName, LastName) VALUES (@FirstName, @LastName)"; 

それはできると思いますが、手動で何かを挿入したくありません。代わりにこれらの両方を実行したい:

  • Datagrid で変更された情報を取得し、取得元の Access データベース ファイル (.mdb) を更新します。
  • 別の Access データベース ファイル (.mdb) からテーブルを取得し、それらをセカンダリ Access データベース ファイル (.mdb) に置き換えることができる関数を作成します。どちらのファイルもまったく同じ構造を使用しますが、異なる情報が含まれています。

誰かがこれに対する答えを出してくれることを願っています...私のプロジェクトは完了しました。待っているのは1つの簡単な答えだけです。

よろしくお願いします。

編集:

わかりました...良いニュースです。.mdb ファイル自体を照会する方法を理解しました (と思います)。使用しようとしているSQLコマンドが原因で実行時エラーが発生するため、機能しないコードを次に示します。それは私の次の質問に私を連れて行きます。

DatabaseHandling.cs に追加された新しい関数コード:

static public void performSynchronization(string table, string tableTwoLocation)
{
    OleDbCommand cmdCopyTables = new OleDbCommand("INSERT INTO" + table + "SELECT * FROM [MS Access;" + tableTwoLocation + ";].[" + table + "]"); // This query generates runtime error
    cmdCopyTables.Connection = dataconnectionA;
    dataconnectionA.Open();
    cmdCopyTables.ExecuteNonQuery();
    dataconnectionA.Close();
}

ご覧のとおり、実際に接続自体でクエリを実行することができました。これは、実際の Access .MDB ファイルであると思われます。私が言ったように、ファイルに対して実行した SQL クエリは機能せず、使用すると実行時エラーが発生しました。

私が実行しようとしているコマンドは、.MDB ファイルからテーブルを取得し、別の .MDB ファイルの同じタイプのテーブルを上書きすることになっています。上記で試みた SQL コマンドは、.mdb ファイルからテーブルを直接取得し、別のファイルに直接配置しようとしましたが、これは私がやりたいことではありません。.MDB ファイルからすべての情報を取得したい - テーブルを Datatable に入れ、すべての Datatables を Dataset に追加します (これを行いました)。これを 2 つの .MDB ファイルに対して行います。2 つのデータセットを取得したら、各データセットから特定のテーブルを取り出し、次のように各ファイルに追加します。

  • DataSetA >>>>----- [テーブル追加(上書き)] ----->>>> DataSetB
  • DataSetB >>>>----- [テーブルを追加 (上書き)] ----->>>> DataSetA

これらの各データセットを取得し、元の各 Access .MDB ファイルに戻します。基本的に両方のデータベースの同期を維持します。

だから私の質問は、改訂されたものです:

  1. 同じ名前の既存のテーブルを上書きして .MDB ファイルにテーブルを追加する SQL クエリを作成するにはどうすればよいですか。クエリは、変数を追加したいテーブル名に置き換える配列を使用して、実行時に動的に作成できる必要があります。
  2. Datagrid によって DataTable に加えられた変更を取得し、それらを DataTable (または DataSet) に戻して、.MDB ファイルに送信できるようにするにはどうすればよいですか?

私は自分の問題をうまく説明していないと思うので、できる限り詳しく説明しようとしました。さて、この質問はあまりにも長くなりすぎました。これをもっとうまく説明できればいいのにと思います。:[

編集:

以下のユーザーのおかげで、私はほぼ修正を見つけたと思います - キーワードほぼ. 以下は、更新された DatabaseHandling.cs コードです。「データ型が一致しません」という実行時エラーが発生します。これらのテーブルをまったく同じセットアップで別のデータベースにコピーしようとしていることを考えると、それがどのように可能になるかわかりません。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Data;
using System.IO;

    namespace LCR_ShepherdStaffupdater_1._0
    {
        public class DatabaseHandling
        {
            static DataTable datatableB = new DataTable();
            static DataTable datatableA = new DataTable();
            public static DataSet datasetA = new DataSet();
            public static DataSet datasetB = new DataSet();
            static OleDbDataAdapter adapterA = new OleDbDataAdapter();
            static OleDbDataAdapter adapterB = new OleDbDataAdapter();
            static string connectionstringA = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationA();
            static string connectionstringB = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationB();
            static OleDbConnection dataconnectionB = new OleDbConnection(connectionstringB);
            static OleDbConnection dataconnectionA = new OleDbConnection(connectionstringA);
            static DataTable tableListA;
            static DataTable tableListB;

            static public void addTableA(string table, bool addtoDataSet)
            {
                dataconnectionA.Open();
                datatableA = new DataTable(table);
                try
                {
                    OleDbCommand commandselectA = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionA);
                    adapterA.SelectCommand = commandselectA;
                    adapterA.Fill(datatableA);
                }
                catch
                {
                    Logging.updateLog("Error: Tried to get " + table + " from DataSetA. Table doesn't exist!");
                }

                if (addtoDataSet == true)
                {
                    datasetA.Tables.Add(datatableA);
                    Logging.updateLog("Added DataTableA: " + datatableA.TableName.ToString() + " Successfully!");
                }

                dataconnectionA.Close();
            }

            static public void addTableB(string table, bool addtoDataSet)
            {
                dataconnectionB.Open();
                datatableB = new DataTable(table);

                try
                {
                    OleDbCommand commandselectB = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionB);
                    adapterB.SelectCommand = commandselectB;
                    adapterB.Fill(datatableB);
                }
                catch
                {
                    Logging.updateLog("Error: Tried to get " + table + " from DataSetB. Table doesn't exist!");
                }



                if (addtoDataSet == true)
                {
                    datasetB.Tables.Add(datatableB);
                    Logging.updateLog("Added DataTableB: " + datatableB.TableName.ToString() + " Successfully!");
                }

                dataconnectionB.Close();
            }

            static public string[] getTablesA(string connectionString)
            {
                dataconnectionA.Open();
                tableListA = dataconnectionA.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
                string[] stringTableListA = new string[tableListA.Rows.Count];

                for (int i = 0; i < tableListA.Rows.Count; i++)
                {
                    stringTableListA[i] = tableListA.Rows[i].ItemArray[2].ToString();
                }
                dataconnectionA.Close();
                return stringTableListA;
            }

            static public string[] getTablesB(string connectionString)
            {
                dataconnectionB.Open();
                tableListB = dataconnectionB.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" });
                string[] stringTableListB = new string[tableListB.Rows.Count];

                for (int i = 0; i < tableListB.Rows.Count; i++)
                {
                    stringTableListB[i] = tableListB.Rows[i].ItemArray[2].ToString();
                }
                dataconnectionB.Close();
                return stringTableListB;
            }

            static public void createDataSet()
            {

                string[] tempA = getTablesA(connectionstringA);
                string[] tempB = getTablesB(connectionstringB);
                int percentage = 0;
                int maximum = (tempA.Length + tempB.Length);

                Logging.updateNotice("Loading Tables...");
                for (int i = 0; i < tempA.Length ; i++)
                {
                    if (!datasetA.Tables.Contains(tempA[i]))
                    {
                        addTableA(tempA[i], true);
                        percentage++;
                        Logging.loadStatus(percentage, maximum);
                    }
                    else
                    {
                        datasetA.Tables.Remove(tempA[i]);
                        addTableA(tempA[i], true);
                        percentage++;
                        Logging.loadStatus(percentage, maximum);
                    }
                }

                for (int i = 0; i < tempB.Length ; i++)
                {
                    if (!datasetB.Tables.Contains(tempB[i]))
                    {
                        addTableB(tempB[i], true);
                        percentage++;
                        Logging.loadStatus(percentage, maximum);
                    }
                    else
                    {
                        datasetB.Tables.Remove(tempB[i]);
                        addTableB(tempB[i], true);
                        percentage++;
                        Logging.loadStatus(percentage, maximum);
                    }
                }


            }

            static public DataTable getDataTableA()
            {
                datatableA = datasetA.Tables[Settings.textA];

                return datatableA;
            }
            static public DataTable getDataTableB()
            {
                datatableB = datasetB.Tables[Settings.textB];
                return datatableB;
            }

            static public DataSet getDataSetA()
            {
                return datasetA;
            }

            static public DataSet getDataSetB()
            {
                return datasetB;
            }

            static public void InitiateCopyProcessA()
            {
                DataSet tablesA;
                tablesA = DatabaseHandling.getDataSetA();

                foreach (DataTable table in tablesA.Tables)
                {
                    CopyTable(table, connectionstringB);
                }
            }

            public static void CopyTable(DataTable table, string connectionStringB)
            {
                var connectionB = new OleDbConnection(connectionStringB);
                foreach (DataRow row in table.Rows)
                {
                    InsertRow(row, table.Columns, table.TableName, connectionB);
                }
            }

            public static void InsertRow(DataRow row, DataColumnCollection columns, string table, OleDbConnection connection)
            {
                var columnNames = new List<string>();
                var values = new List<string>();

                for (int i = 0; i < columns.Count; i++)
                {
                    columnNames.Add("[" + columns[i].ColumnName + "]");
                    values.Add("'" + row[i].ToString().Replace("'", "''") + "'");
                }

                string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})",
                        table,
                        string.Join(", ", columnNames.ToArray()),
                        string.Join(", ", values.ToArray())
                    );

                ExecuteNonQuery(sql, connection);
            }

            public static void ExecuteNonQuery(string sql, OleDbConnection conn)
            {
                if (conn == null)
                    throw new ArgumentNullException("conn");

                ConnectionState prevState = ConnectionState.Closed;
                var command = new OleDbCommand(sql, conn);
                try
                {
                    prevState = conn.State;
                    if (prevState != ConnectionState.Open)
                        conn.Open();

                    command.ExecuteNonQuery(); // !!! Runtime-Error: Data type mismatch in criteria expression. !!!
                }
                finally
                {
                    if (conn.State != ConnectionState.Closed
                        && prevState != ConnectionState.Open)
                        conn.Close();
                }
            }

            }          
        }

このエラーが発生するのはなぜですか? 両方のテーブルはまったく同じです。私は何を間違っていますか?最悪の場合、まったく同じ構造のテーブルを別の値で挿入する前に、別の Access .MDB ファイルのテーブルを削除するにはどうすればよいですか?

男私はこれを理解できたらいいのに...

編集:

よし、だいぶ離れた。私の質問は新しいものに変化したため、個別に質問する価値があります。開いた接続に対して直接クエリを実行する方法がわかったので、質問に答えてもらいました。皆さん、ありがとうございました!

4

4 に答える 4

3

どこまで進んだかはわかりませんが、すばやくドラッグアンドドロップ操作を行う場合は、接続する厳密に型指定されたデータセットを作成し、データソースツールウィンドウのドラッグアンドドロップ機能を使用することを検討してください。 VisualStudioで。

確かにそこにサンプルがありますが、あなたはしたいと思うでしょう。

  1. 新しいデータセットを作成する
  2. サーバーエクスプローラーのDataConnectionツリーからドラッグアンドドロップ
  3. 新しいフォームを作成する
  4. データソースツールからテーブルをドラッグします
  5. フォームへのウィンドウ。
  6. 出来上がり

アップデート:

まず、私はあなたの問題を100%理解しているわけではありません。アクセスファイル間に最適なLinkTableを作成できる場合は、「INSERT INTO Customers SELECT FirstName、LastName FROM File2.Customers」などのSQLステートメントを使用して、ファイル間でデータをコピーできます。そうでない場合はオプションで、DataTablesをループし、最後の編集と同様のINSERTステートメントを使用してレコードを手動で挿入する必要があると思います。データグリッドに関しては、行が変更されたときに挿入/更新ステートメントを実行するRowChangedイベント(正確なイベントかどうかはわかりません)を監視して、変更内容を追跡する必要があります。

アップデート:

データテーブルをループするには、次のようにします。未検証。MakeValueDbReady関数を含めるために、これを再度更新しました。これもテストされておらず、すべてのケースを処理したのか、それともすべてのケースを正しく処理したのかわかりません。sqlステートメントを実際にデバッグし、正しい値が生成されることを確認する必要があります。データベースが処理する値はそれぞれ異なります。少なくともこの方法で、解析された値が抽出されます。また、TableNameをハードコーディングする代わりに、DataTableのプロパティから取得できるようにする必要があることにも気づきました。

void CopyTable(DataTable table, string connectionStringB)
{
    var connectionB = new OleDbConnection(connectionStringB);
    foreach(DataRow row in table.Rows)
    {
        InsertRow(row, table.Columns, table.TableName, connectionB);
    }
}

public static void InsertRow(DataRow row, DataColumnCollection columns, string table, OleDbConnection connection)
{
    var columnNames = new List<string>();
    var values = new List<string>();

    // generate the column and value names from the datacolumns    
    for(int i =0;i<columns.Count; i++)
    {
        columnNames.Add("[" + columns[i].ColumnName + "]");
        // datatype mismatch should be fixed by this function
        values.Add(MakeValueDbReady(row[i], columns[i].DataType));
    }

    // create the sql
    string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})",
            table,
            string.Join(", ", columnNames.ToArray()),
            string.Join(", ", values.ToArray())
        );

    // debug the accuracy of the sql here and even copy into 
    // a new Query in Access to test
    ExecuteNonQuery(sql, connection);
}

// as the name says we are going to check the datatype and format the value
// in the sql string based on the type that the database is expecting
public string MakeValueDbReady(object value, Type dataType)
{
    if (value == null)
        return null;

    if (dataType == typeof(string))
    {
        return "'" + value.ToString().Replace("'", "''") + "'"
    }
    else if (dataType == typeof(DateTime))
    {
        return "#" + ((DateTime)value).ToString + "#"
    }
    else if (dataType == typeof(bool))
    {
        return ((bool)value) ? "1" : "0";
    }

    return value.ToString();
}

public static void ExecuteNonQuery(string sql, OleDbConnection conn)
{
    if (conn == null)
        throw new ArgumentNullException("conn");

    ConnectionState prevState = ConnectionState.Closed;
    var command = new OleDbCommand(sql, conn);
    try
    {
        // the reason we are checking the prev state is for performance reasons
        // later you might want to open the connection once for the a batch
        // of say 500 rows  or even wrap your connection in a transaction.
        // we don't want to open and close 500 connections
        prevState = conn.State;
        if (prevState != ConnectionState.Open)
            conn.Open();

        command.ExecuteNonQuery();
    }
    finally
    {
        if (conn.State != ConnectionState.Closed
            && prevState != ConnectionState.Open)
            conn.Close();
    }
}
于 2009-02-05T22:45:40.460 に答える
1

元の MDB ファイルをDataSetに加えられた変更で更新するには(DataGrid ではなく、DataSet に対する単なる UI であるため)、DataAdapter.Updateコマンドを使用します。

テーブルを 1 から別のテーブルに移動するのは少し面倒です。宛先にテーブルがまだ存在しない場合は、SQL CREATE ステートメントを使用して作成する必要があります。次に、ソースからDataAdapter.Fillを DataSet にします。各行をループし、 DataRow.SetAdded を呼び出してその状態を RowAdded に設定します次に、宛先データベースから DataAdapter.Update に戻します。

編集:コードは次の質問にあります....

于 2009-02-06T04:02:40.087 に答える
0

拡張子が .mdb のファイルには、実際には複数の形式があります。したがって、間違ったものを推測すると、これは間違った答えになります。ただし、Microsoft Access の問題のようです。

MDB ファイルに直接書き込むことはありません。それらは暗号化され、圧縮されています。MDB ファイルを変更する最も簡単な方法は、Access を使用してファイルを読み込み、提供されている方法でテーブルをコピーすることです。

于 2009-02-05T22:28:27.343 に答える
0

データベース (.mdb ファイル) にどのように接続していますか? サンプルコードを投稿できますか?正しく接続している場合、それに対して実行する SQL 操作はデータベースに自動的に保存されます。

したがって、データベースに接続した後、テーブルの作成、データの挿入/更新/取得などを行う SQL を実行できます。手動で .mdb ファイルを構築しようとすることはお勧めできません。

次に例を示します。

http://www.java2s.com/Code/CSharp/Database-ADO.net/Access.htm

于 2009-02-05T23:02:35.340 に答える