質問: dt; } } catch (Exception ex) { MessageBox.Show(ex.Message); return; } ``` adapter.Fill(dt); を実行した際に、エラーとして以下の内容が表示されます。 エラー内容 ERROR[42000][Microsoft][ODBC Microsoft Access Driver] 'MSysObjects'の読み取り権限がないので、レコードを読み取ることができません。 .NETからAccess2013のテーブル名称情報を取得することは無理なのでしょうか?
回答: > > .NetからAccess2013への接続、データ取得はうまくいきましたが、Accessのテーブル名称を取得する際に権限のエラーが出てしまいます。 > > > DataTable に Access のテーブルからデータを取得できていて、DataGridView には表示できるということですか? で、「Accessのテーブル名称を取得」とはどういうことでしょう? 質問に提示されているコードにはそのような操作は入ってないように見えますが、その操作が入っているとすると具体的にコードのどれですか? それから、上記と、 > > adapter.Fill(dt); を実行した際に、エラーとして以下の内容が表示されます。 > > > で言っていることが矛盾していませんか。adapter.Fill(dt) でエラーが出るということはデータの取得はうまくいってないということだと思うのですが? ・・・というように、意味が分からないことが多々ありますが、とりあえず一度 Visual Studio のウィザードを使って定番の構成のアプリを作ってみることを提案させてください。 DB が SQL Server の場合ですが、以下のチュートリアル、 チュートリアル : データベースへのデータの保存 (単一テーブル) ・・・のように Visual Studio のデータソース構成ウィザードを利用して型付 DataSet + TableAdapter を作って、それを利用してアプリを作ると、以下のページの図のような構造のアプリが、ほとんど自分でコードを書くこと無しに作れます。 Windows フォーム アプリケーションでのデータへの接続 Access でもウィザードが使えますので、同様なことができます。(注) 操作に慣れると 10 分もかからず作れるはずです。今回のような問題に悩むことはなくなり、開発工数は激減するはずです。保守工数も減るはずです。お試しください。 (注)Access でオートナンバーを使っている場合、INSERT した時に DB 側で設定したオートナンバー値を DataSet に書き込むところまでは面倒を見てくれないという点が SQL Server とは違いまが、それを解決する方法はあります。詳しくは以下の記事を見てください。 Access の更新 **【追伸】** 今回の問題とは関係ない余計なお世話かもしれませんが、Exception をキャッチするのは止めた方がいいです。理由は以下の記事を見てください。 NETの例外処理 Part.1 .NETの例外処理 Part.2 .NET 4 からは破損状態例外は catch できなくなっているそうですが、「それでも Catch (Exception e) を使用するのはよくない」ということについては以下の記事を見てください。 破損状態例外を処理する **【2018/3/2 13:30 追記】** 下の 2018/03/02 12:50 の私のコメントで「OleDbConnection.GetSchema メソッドを利用するのがよさそうです。具体的な方法は別途回答欄に追記しておきます」と書きましたが、それを以下に書きます。 詳しい説明が書いてある Microsoft の文書が見つからず、やってみた結果で判断してますので、ホントにそれで全てのケースで問題なくテーブル名が取得できるのかという不安は若干ありますが・・・ OleDbConnection.GetSchema メソッド (String) の引数(返すスキーマの名前)を "Tables" とすると、テーブルのスキーマ情報(テーブル名を含む)を格納した DataTable が返ってきます。 OleDbConnection.GetSchema メソッド (String) DataTable の中には VIEW やシステムテーブルも含まれていますが、テーブルの種類の情報も含まれているのでそれを見てテーブル名のみを取得できます。 DataTable の 3 番目の列にテーブル名が、4 番目の列に種類が格納されているので、種類が "TABLE" ものを取得すれば良いはずです。 以下のコードは、Microsoft のサンプル Northwind2007.accdb からその中のテーブル名を取得する例です。 ``` using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.OleDb; using System.Data; using System.Data.SqlClient; namespace ConsoleAppAccess { class Program { static void Main(string[] args) { using (OleDbConnection conn = new OleDbConnection()) { conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\"C:\\Users\\...\\Northwind2007.accdb\""; conn.Open(); string collectionName = "Tables"; DataTable table = conn.GetSchema(collectionName); foreach (DataRow dataRow in table.Rows) { if (dataRow[3].ToString() == "TABLE") { Console.WriteLine(dataRow[2]); } } } } } } ``` 結果は以下の通りで、Northwind2007.accdb に含まれるテーブル名として間違いないことは確認しました。 Budget Categories Categories 2003 Customers Customers 2003 Employee Privileges Employees Employees 2003 Inventory Transaction Types Inventory Transactions Invoices Monthly Orders Order Details Order Details 2003 Order Details Status Orders Orders 2003 Orders Status Orders Tax Status Privileges Products Products 2003 Purchase Order Details Purchase Order Status Purchase Orders Sales Reports Shippers Strings Suppliers Suppliers 2003 Switchboard Items