質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

ADO.NET

ADO.NETは.NET Frameworkで各種データベースへの統一された接続機能を提供するソフトウェアコンポーネントの集合です。

Q&A

解決済

2回答

1762閲覧

ADO.net Accdbファイルのデータテーブルの主キーフィールドが確認出来ません。

masakifukuta

総合スコア58

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

ADO.NET

ADO.NETは.NET Frameworkで各種データベースへの統一された接続機能を提供するソフトウェアコンポーネントの集合です。

0グッド

0クリップ

投稿2021/11/23 18:41

編集2021/11/24 07:01

C#にてAccDBファイルのデータを扱うコードを書いています。

SQL構文にてデータテーブルを作成しました。

CREATE TABLE [名簿] ([INDEX] INT IDENTITY(1,1) PRIMARY KEY ,NUMBER VARCHAR(10) NOT NULL ,[氏名] VARCHAR(10) NOT NULL ,[入所年月日] DATE );

作成されたデータテーブルから,主キー(PRIMARY KEY)が設定されたフィールドを確認したいのですが、
下記のコードで主キー(PRIMARY KEY)が設定されたフィールドを取得出来ません。

public bool GetKeyDataField(DataTable data) { DataColumn[] keycolumn = data.PrimaryKey; foreach(DataColumn dataColumn in keycolumn) { Console.WriteLine(dataColumn.ColumnName); } }

参照
https://docs.microsoft.com/ja-jp/dotnet/api/system.data.datatable.primarykey?view=net-6.0

SQL構文にて別のフィールドにもPRIMARY KEYを設定しようとすると、
すでに主キーが設定されている旨のエラーが出ますので、DataTableの作成には問題無いと思います。

上記の方法に問題があるのか、他の方法があるのか、教えて頂けないでしょうか。
宜しくお願い致します。

データベース?は"Microsoft.ACE.OLEDB.12.0"を使用しています。
AccDBファイルの作成

ADOX.Catalog cat = new Catalog(); cat.Create(DBSource); OleDbConnection connection = new OleDbConnection(Builder.ConnectionString); DBSourceの内容 "Provider = Microsoft.ACE.OLEDB.12.0; Data Source = C:\Users\xxxx\OneDrive\共有\DataBase\test2.accdb" コード

SQL実行クラス

protected

1 { 2 try 3 { 4 //connection.Open(); 5 System.Data.OleDb.OleDbCommand command = connection.CreateCommand(); 6 command.CommandText = queryString; 7 command.CommandTimeout = 30; 8 command.ExecuteNonQuery(); 9 command.Dispose(); 10 return true; 11 } 12 catch (Exception ex) 13 { 14 returnMessage = ex.Message; 15 Log.Write(returnMessage + queryString); 16 connection.Close(); 17 return false; 18 } 19 } 20コード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/11/23 21:13 編集

DB は何かとそのバージョンを書いてください。 accdb とあるから Access ですか? Access は identity ではなくて autonumber になると思うのですが、create 文は合ってますか? 問題の DataTable をどのように作ったか書いてください。
masakifukuta

2021/11/24 06:59

早速のアドバイスありがとうございます。現場作業があるのでPCに触れられる時間が限られており、 素早いレスポンスが出来ません。すいません。 AccDBファイルの作成,Table作成のSQL実行のコードを追記しました。 SQL分中のIDENTITYをAUTO NUMBERに変更した所、SQL構文の構文エラーが出ましたので、 IDENTITYで良いのだと思います。
退会済みユーザー

退会済みユーザー

2021/11/24 07:09

create 文で table を作る場合は autonumber ではなく autoincrement を使うはずです。 何にせよ DB は Access で間違いなく主キーは autonumber なのですね?
退会済みユーザー

退会済みユーザー

2021/11/24 07:15 編集

回答に書いたように「DataTable は DbDataAdapter.Fill メソッドで SELECT クエリをベースに生成したもので、生成された DataTable から PrimaryKey プロパティを使って主キーを調べたいという話であろうと想像した」のですが、その想像はあってますか? 質問にコードを追記したようですが、それのどこにも DataTable を作っているものは無いのですが。想像が違っていたらどこがどう違うのか教えてください。
masakifukuta

2021/11/24 18:13

度々ありがとうございます。 DataBaseにデータを追加する際、新規データなのかデータ更新なのかを判別するために キーを検索する汎用クラスを作成しようとしています。 回答者様の指摘通り、DataBaseはCREATE TABLEクエリで作成した物で、 SELECT文で抽出した物ではありませんでした。 改めてコードを考えてみます。 有難うございました。
退会済みユーザー

退会済みユーザー

2021/11/25 00:45 編集

私の想像はハズレ・・・と言うか、質問者さんは全く見当はずれのことを考えていたのでは? > 回答者様の指摘通り、DataBaseはCREATE TABLEクエリで作成した物で、SELECT文で抽出した物ではありませんでした。 まず、データベース (Access) のテーブルと .NET Framework (ADO.NET) のライブラリに含まれる DataTable クラスを混同してませんか? であれば、そのあたりをよく調べて基本的な知識を得て、全く違うものであるという認識を持ってください。 > DataBaseにデータを追加する際、新規データなのかデータ更新なのかを判別するためにキーを検索する汎用クラスを作成しようとしています。 そこも意味不明です。元々の話はデータベースの既存のテーブルの主キーのフィールドが何かを調べたいという話であったはず。 上記が既存のテーブルに新規レコードを登録する場合の話だとすると、主キーのフィールドが何かを調べて、追加するデータが既存のデータとダブらないか確認(同じ主キー値がないか確認)するということ? でも、主キーはオートナンバーですよね? 主キーを調べても意味がないです。
masakifukuta

2021/11/25 06:14

複数のテーブルがあり、それぞれにキー列が設定されています。キー列はインデックスだったり、日付だったり一貫性がありません。これらについて一つのクラスでデータを追加・更新できるように、 与えられたテーブルのキー列を判別し新規か更新かまだ分からないデータとキーを照合して、 INSERT句かUPDATE句を作成するクラスを作成したいと思いました。 まだまだ理解が足らないので勉強いたします。 アドバイスありがとうございました。
退会済みユーザー

退会済みユーザー

2021/11/25 23:48

> これらについて一つのクラスでデータを追加・更新できるように、 与えられたテーブルのキー列を判別し新規か更新かまだ分からないデータとキーを照合して、INSERT句かUPDATE句を作成するクラスを作成したいと思いました。 依然として意味不明です。特に、「キー列を判別し新規か更新かまだ分からないデータとキーを照合」辺りに見当違いがあると思います。 次回質問することがありましたら、その辺りをよく説明して自分のやりたいことが他人に分かるようにしてください。 また、ぜひこれをよく読んでからにしてください⇒ https://teratail.com/help/question-tips 特にこのあたり: "人に質問をするには、自分が何を尋ねたいかを知っている必要があります。これは、「自分が今『何がわからないのか』がわかっていて、言語化できている」ということです。一見簡単なようですが、実はとても難しいことです。何がわからないかわからない人から質問を受けても、答える側も困ってしまいます。"
guest

回答2

0

ベストアンサー

質問に対するコメントに返事が無いのでいろいろ不明ですが、DataTable は DbDataAdapter.Fill メソッドで SELECT クエリをベースに生成したもので、生成された DataTable から PrimaryKey プロパティを使って主キーを調べたいという話であろうと想像してレスします。

DbDataAdapter.Fill メソッドで生成された DataTable には主キーなどのスキーマは含まれません。DbDataAdapter.FillSchema メソッドを使ってスキーマを設定する必要があります。

SQL Server の例ですが、以下のテーブルを対象にすると、

CREATE TABLE [dbo].[Products]( [ProductID] [int] IDENTITY(1,1) NOT NULL, [ProductName] [nvarchar](40) NOT NULL, [SupplierID] [int] NULL, [CategoryID] [int] NULL, [QuantityPerUnit] [nvarchar](20) NULL, [UnitPrice] [money] NULL, [UnitsInStock] [smallint] NULL, [UnitsOnOrder] [smallint] NULL, [ReorderLevel] [smallint] NULL, [Discontinued] [bit] NOT NULL, CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ( [ProductID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

以下のようにして主キーを調べることが出きます。

using System; using System.Data; using System.Data.SqlClient; namespace ConsoleAppFillSchema { internal class Program { static void Main(string[] args) { DataTable table = CreateDataTable(); DataColumn[] columns = table.PrimaryKey; foreach (DataColumn dataColumn in columns) { Console.WriteLine(dataColumn.ColumnName); } } public static DataTable CreateDataTable() { DataTable dt = new DataTable(); string connString = @"Data Source=lpc:(local)\sqlexpress;Initial Catalog=NORTHWIND;Integrated Security=True"; string query = "SELECT [ProductID],[ProductName],[SupplierID],[CategoryID],[UnitPrice] FROM [NORTHWIND].[dbo].[Products]"; using (var conn = new SqlConnection(connString)) { using (var cmd = new SqlCommand(query, conn)) { var adapter = new SqlDataAdapter(); adapter.SelectCommand = cmd; adapter.Fill(dt); // 主キーなどのスキーマは以下のようにしないと設定 // されない(自動的には設定されない) dt = adapter.FillSchema(dt, SchemaType.Mapped); // または //dt.PrimaryKey = new DataColumn[] { dt.Columns["ProductID"] }; } } return dt; } } }

結果は:

イメージ説明

Access で使う OleDbDataAdapter でもたぶん同じだと思います(未検証ですが)。

投稿2021/11/24 03:25

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masakifukuta

2021/11/24 07:08

回答ありがとうございます。直ぐには出来ませんが、頂いた情報を元にやってみます。
退会済みユーザー

退会済みユーザー

2021/11/24 07:16

上の回答に書いたように「DataTable は DbDataAdapter.Fill メソッドで SELECT クエリをベースに生成したもので、生成された DataTable から PrimaryKey プロパティを使って主キーを調べたいという話であろうと想像」したのですが、その想像はあってますか? 質問にコードを追記したようですが、それのどこにも DataTable を作っているものは無いのですが。想像が違っていたらどこがどう違うのか教えてください。
guest

0

OleDbConnection.GetOleDbSchemaTable で様々な情報が取得できます。
OleDbSchemaGuid.Primary_Keys を第一引数に指定するとプライマリーキーの情報が取得できます。

以下のサンプルは accdb を作成するために、Microsoft ADO Ext. XX for DDL and Security の参照が必要です。
32ビットでしか動作しません。
Access のランタイムも 32ビットである必要があります。

C#

1using System; 2using System.Data.OleDb; 3using System.IO; 4using System.Runtime.InteropServices; 5using System.Text; 6 7class Program 8{ 9 static void Main(string[] args) { 10 11 const string fileName = @"D:\TEST\TEST.accdb"; 12 const string tableName = @"TEST_TABLE"; 13 14 // 接続文字列の作成 15 var builder = new OleDbConnectionStringBuilder(); 16 builder.Provider = "Microsoft.ACE.OLEDB.12.0"; 17 builder.DataSource = fileName; 18 19 // .accdb が無ければ作る 20 if (!File.Exists(fileName)) { 21 ADOX.Catalog catalog = new ADOX.Catalog(); 22 catalog.Create(builder.ConnectionString); 23 Marshal.ReleaseComObject(catalog); 24 } 25 26 // 接続 27 var con = new OleDbConnection(builder.ConnectionString); 28 con.Open(); 29 30 // テーブルが無ければ作成する 31 using (var dt = con.GetOleDbSchemaTable( 32 OleDbSchemaGuid.Tables, 33 new object[] { null, null, tableName })) { 34 if (dt.Rows.Count == 0) { 35 using (var cmd = con.CreateCommand()) { 36 var sql = new StringBuilder(); 37 sql.AppendLine("CREATE TABLE " + tableName + "("); 38 sql.AppendLine(" ITEM_KEY AUTOINCREMENT PRIMARY KEY"); 39 sql.AppendLine(", ITEM_DATA Text(3)"); 40 sql.AppendLine(")"); 41 cmd.CommandText = sql.ToString(); 42 cmd.ExecuteNonQuery(); 43 } 44 } 45 } 46 47 // プライマリーキーの情報を取得して xml で出力 48 using (var dt = con.GetOleDbSchemaTable( 49 OleDbSchemaGuid.Primary_Keys, 50 new object[] { null, null, tableName })) { 51 dt.WriteXml(Console.Out); 52 } 53 54 Console.ReadKey(); 55 } 56}

出力結果

XML

1<DocumentElement> 2 <Primary_Keys> 3 <TABLE_NAME>TEST_TABLE</TABLE_NAME> 4 <COLUMN_NAME>ITEM_KEY</COLUMN_NAME> 5 <ORDINAL>1</ORDINAL> 6 <PK_NAME>Index_40AB00BA_D994_4A1C</PK_NAME> 7 </Primary_Keys> 8</DocumentElement>

参考URL

「OleDbConnection.GetOleDbSchemaTable(Guid, Object[]) メソッド」
https://docs.microsoft.com/ja-jp/dotnet/api/system.data.oledb.oledbconnection.getoledbschematable?view=netframework-4.8

「OleDbSchemaGuid クラス」
https://docs.microsoft.com/ja-jp/dotnet/api/system.data.oledb.oledbschemaguid?view=netframework-4.8

投稿2021/11/24 00:19

編集2021/11/24 00:38
KOZ6.0

総合スコア2639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masakifukuta

2021/11/24 07:10

回答ありがとうございます。 大変興味深い情報です。 参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問