C#でAccessファイル(.accdb)を操作する

OLEDBで.accdbへ接続します。
### ０．using
```C#
using System.Data.OleDb;  //宣言を短くする為追加しておく
```

### １．テーブル名カラム名取得
```C#
        OleDbConnectionStringBuilder builder;

        private void Form_Load(object sender, EventArgs e)
        {
            builder = new OleDbConnectionStringBuilder();
            builder["Provider"] = "Microsoft.ACE.OLEDB.12.0";
            builder["Data Source"] = "C:\\・・・\\データベース名.accdb";
            //builder["Jet OLEDB:Database Password"] = "abcde";
        }
        
        private void buttonテーブル名カラム名取得_Click(object sender, EventArgs e)
        {
            Console.WriteLine("----------テーブル名-----------");
            using (var cn = new System.Data.OleDb.OleDbConnection(builder.ConnectionString))
            {
                cn.Open();
                var dt = cn.GetSchema("Tables");
                foreach (DataRow row in dt.Rows)
                {
                    var tableName = row["TABLE_NAME"].ToString();
                    Console.WriteLine(tableName);
                }
                cn.Close();
            }

            Console.WriteLine("----------テーブル名+カラム名-----------");
            using (var cn = new OleDbConnection(builder.ConnectionString))
            {
                cn.Open();
                var dt = cn.GetSchema("Columns");
                foreach (DataRow row in dt.Rows)
                {
                    var tableName = row["TABLE_NAME"].ToString();
                    var fieldName = row["COLUMN_NAME"].ToString();
                    var text = string.Format("{0}.{1}", tableName, fieldName);
                    Console.WriteLine(text);
                }
                cn.Close();
            }
        }
        
```
### ２．テーブル作成/削除
```C#
        private void buttonCreateTable_Click(object sender, EventArgs e)
        {
            Console.WriteLine("----------テーブル作成-----------");
            using (var cn = new OleDbConnection(builder.ConnectionString))
            {
                //テーブル作成の場合
                string  sql ="";
                    sql += "CREATE TABLE テスト([社員番号] TEXT, [氏名] TEXT, [部門] TEXT";
                    sql += " ,CONSTRAINT [PrimaryKey] PRIMARY KEY ([社員番号]) )";

                //テーブル作削除の場合
                string sql = "DROP TABLE テスト";

                try
                {
                   cn.Open();
                    // Connection + SQL
                    var cmd = new OleDbCommand(sql, cn);
                    // ExecuteNonQuery
                    cmd.ExecuteNonQuery();
                    MessageBox.Show("テーブルを作成/削除しました。", "通知");
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.Message, "通知");
                }
                finally
                {
                    cn.Close();
                }
            }
        }
  
```

### ３．Insert文
```C#
        private void buttonInsert_Click(object sender, EventArgs e)
        {
            Console.WriteLine("----------Insert文-----------");
            using (var cn = new OleDbConnection(builder.ConnectionString))
            {
                string 
                    sql  = "INSERT INTO テスト ([社員番号], [氏名], [部門])";
                    sql += " VALUES('123456', '大山 雪男', '企画');";

                    //sql += "insert into テスト ([社員番号], [氏名], [部門])";
                    //sql += " values('112233', '海原 鯨子', '販売');";
                    //連続不可。CSVファイルにして…もあるようだが面倒。

                try
                {
                    cn.Open();
                    // Connection + SQL
                    var cmd = new System.Data.OleDb.OleDbCommand(sql, cn);  
                    // ExecuteNonQuery
                    cmd.ExecuteNonQuery();
                    MessageBox.Show("insertしました。", "通知");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "通知");
                }
                finally
                {
                    cn.Close();
                }
            }
        }
   
```


### ４．トランザクション付きデータ処理
SQLをListにして渡しちゃえ！
```C#
        private string トランザクション付きデータ処理(List<string> sql)
        {
            Console.WriteLine("----------トランザクション付きデータ処理-----------");

            using (OleDbCommand cmd = new OleDbCommand())
            {
                OleDbConnection cn = new OleDbConnection();
                cn.ConnectionString = builder.ConnectionString;

                // トランザクションを開始します。
                cn.Open();
                OleDbTransaction transaction = cn.BeginTransaction(IsolationLevel.ReadCommitted);

                try
                {
                    cmd.Connection = cn;
                    cmd.Transaction = transaction;

                    foreach (var s in sql)
                    {
                        cmd.CommandText = s;
                        cmd.ExecuteNonQuery();
                    }

                    //トランザクションをコミットします。
                    transaction.Commit();
                    MessageBox.Show("正常完了しました。", "通知");
                    return "OK";
                }
                catch (Exception ex)
                {
                    //トランザクションをロールバックします。
                    transaction.Rollback();
                    MessageBox.Show(ex.Message, "通知");
                    return "NG";
                }
                finally
                {
                    cn.Close();
                }
        }
```

### ５．Select文
```C#
        private void buttonSelect_Click(object sender, EventArgs e)
        {
            Console.WriteLine("----------Select文-----------");
            using (var cn = new OleDbConnection(builder.ConnectionString))
            {
                string sql = "SELECT * FROM テスト";

                OleDbCommand command = new OleDbCommand(sql, cn);
                cn.Open();
                OleDbDataReader reader = command.ExecuteReader();

                while (reader.Read())
                {
                    //Console.WriteLine(reader[0].ToString());
                    Console.WriteLine("結果⇒ {0} / {1} / {2}", reader["社員番号"].ToString(), reader["氏名"].ToString(), reader["部門"].ToString());
                }
                reader.Close();
            }
        }
        
```

### ６．一発でDataGridViewに表示する。
```C#
            using (var cn = new OleDbConnection(Access接続文字列))
            {
                // Accessのデータベースファイルに接続する
                cn.Open();

                string sql = "SELECT * FROM ・・・";

                // OleDbCommandインスタンスを生成する
                using (OleDbCommand command = new OleDbCommand(sql, cn))
                {
                    // OleDbDataAdapterインスタンスを生成する
                    using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
                    {
                        // DataTableインスタンスを生成する
                        DataTable dt = new DataTable();
                        // データテーブルにデータを格納する
                        adapter.Fill(dt);
                        // DataGridViewにデータを表示する
                        dataGridView1.DataSource = dt;
                    }
                }
            }
```
### ７．accdbファイルを最適化する

とても時間が掛かったのでメモ残します。

１)参照の追加
　　[プロジェクト]→[参照の追加]で、
　　Microsoft.Office.Interop.Access.Daoを追加します。
![DAO参照.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157849/63b921ab-e0bf-0597-079e-6a8530696a8f.png)



２）コード
```C#
using Microsoft.Office.Interop.Access.Dao; //最適化用
using System.IO;                           //ファイル操作用

        private void button最適化_Click_1(object sender, EventArgs e)
        {
            //DBEngine dbe = new DBEngineClass();  //←これだと相互運用型云々のエラー出る。
            DBEngine dbe = new DBEngine();

            string before = @"～パス～\DB.accdb";         //オリジナルのアクセスファイル
            string after  = @"～パス～\DBd_done.accdb";   //最適化後のアクセスファイル

            if (File.Exists(after)) // 前のファイルが残っていたら削除(念の為)
            {
                File.Delete(after);
            }

            dbe.CompactDatabase(before, after, null, null, null);

            File.Delete(before);
            File.Move(after, before);
        }
```        
こうするとこんなエラーになります。
![相互運用型エラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157849/c6382176-826b-d70c-3cb0-66871c1c4aa1.png)