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

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

新規登録して質問してみよう
ただいま回答率
85.35%
DataSet

DataSetは、ADO.NETアーキテクチャのコンポーネントです。データベースから取得したレコードをメモリ領域に格納するクラスを指します。データの保持やテーブル間のリレーション・制約といった保持も可能です。

Oracle Database

Oracle Databaseは、米オラクルが開発・販売を行うリレーショナルデータベース管理システムです。

C#

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

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Q&A

解決済

1回答

5637閲覧

oracleから抽出したデータとDataTableを結合したい

AEGIL

総合スコア7

DataSet

DataSetは、ADO.NETアーキテクチャのコンポーネントです。データベースから取得したレコードをメモリ領域に格納するクラスを指します。データの保持やテーブル間のリレーション・制約といった保持も可能です。

Oracle Database

Oracle Databaseは、米オラクルが開発・販売を行うリレーショナルデータベース管理システムです。

C#

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

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

0グッド

0クリップ

投稿2020/11/09 09:12

編集2020/11/10 02:41

実現したいこと

DataTable(table)にcsvtableとoracleTableのデータを結合したものを表示したい
###不明点
DataTableを二つ用意してから任意のデータをもってきたいと思ったのですが、下記コードのoracleから取り込んだデータを持ってきたいという箇所にどうやってデータを投入したらよいかがわかりません。

c#

1 private void Button_Click_1(object sender, EventArgs e) 2 { 3 //Csv読み込んだファイル呼ぶ 4 DataTable csvtable = Csv(textBox1.Text); 5 //オラクルからデータを抽出する 6 using (OracleConnection conn = new OracleConnection()) 7 { 8 string DataSource = //"oracleへのパス"; 9 conn.ConnectionString = DataSource; 10 //コネクションオープン 11 conn.Open(); 12 using (OracleCommand cmd = new OracleCommand(select * from TABLE名) 13 { 14 cmd.Connection = conn; 15 using (OracleDataReader reader = cmd.ExecuteReader()) 16 { 17 DataTable oracleTable = new DataTable(); 18 oracleTable.Load(reader); 19 dataGridView2.DataSource = oracleTable; 20 } 21 } 22 } 23 //結合する 24 25 //レイアウト変更用のDataTable作成 26 DataTable table = new DataTable("ReasultDataTable"); 27 table.Columns.Add("名前", typeof(string)); 28 table.Columns.Add("年齢", typeof(string)); 29 table.Columns.Add("性別", typeof(string)); 30 table.Columns.Add("職業", typeof(string)); 31 table.Columns.Add("出身", typeof(string)); 32 //新規のレイアウトにcsv内のデータを投入する 33 foreach (DataRow csvrow in csvtable.Rows) 34 { 35 DataRow dtRow = table.NewRow(); 36 37 dtRow["名前"] = csvrow["name"];//Csv(textBox1.Text)内の列データをdtRowに挿入 38 dtRow["年齢"] = csvrow["age"];//Csv(textBox1.Text)内の列データをdtRowに挿入 39 dtRow["性別"] = csvrow["gender"];//Csv(textBox1.Text)内の列データをdtRowに挿入 40 41 //oracleから取り込んだデータを持ってきたい 42 dtRow["職業"] = csvrow["age"];//オラクルデータ挿入 43 dtRow["出身"] = csvrow["gender"];//オラクルデータ挿入 44 45 table.Rows.Add(dtRow); 46 } 47 dataGridView1.DataSource = table; 48 }

###開発環境
VisualStudio2017

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

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

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

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

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

Orlofsky

2020/11/09 09:30

> ※実際に動作させる際は、select文も*ではなく細かく定めております。その上で30秒かかってしまいます。 そのSELECT文とCREATE TABLE, CREATE INDEX, テーブル毎のレコード件数、実行計画を質問に追記しないと適切なコメントが付くのは難しいでしょう。テーブル名や列名を適当に置換すれば提示しても構わないはず。また、ちゃんと統計情報を収集していますか? Oracle 統計情報の収集 https://www.shift-the-oracle.com/performance-tuning/dbms_statistics.html Oracle EXPLAIN PLAN を使って実行計画を取得する https://www.shift-the-oracle.com/sql/explain-plan.html
退会済みユーザー

退会済みユーザー

2020/11/09 23:29

質問は何なのですか? 表題を見ると 2 つの DataTable を join するクエリ (Linq to Object?) の書き方のように思えますが、中身を見ると Oracle からデータを取得する時間短縮の質問に見えます。
AEGIL

2020/11/10 02:44

統計情報に関しては収集しておりませんでした。実現したいこと質問したいことは結合部分についてが主なので編集させていただきました。誤解を生んでしまい申し訳ありません。
退会済みユーザー

退会済みユーザー

2020/11/11 01:15

質問者さん、無言になってしまいましたが、回答したのでそれに対するフィードバックを書いてください。役に立った/立たなかったくらいはすぐにでも書けると思いますけど。役に立たなかっらなら、どこが期待する回答と違うかなど書いてもらえると別の案が出せるかも。とにかく無言は NG です。
guest

回答1

0

ベストアンサー

DataTableを二つ用意してから任意のデータをもってきたいと思ったのですが、下記コードのoracleから取り込んだデータを持ってきたいという箇所にどうやってデータを投入したらよいかがわかりません。

DataTable ではなく List<T> 型のオブジェクトに SQL Server と CSV ファイルのレコードを取得し、Linq to Objects を使って内部結合または左外部結合する例ですが、以下の記事が参考になりませんか?

異なるデータソースの結合と表示
http://surferonwww.info/BlogEngine/post/2017/11/26/how-to-join-and-show-the-records-from-different-data-sources.aspx

SQL Server でなく Oracle の場合でも ADO.NET + ODP.NET を使って同じことができるはずです。

List<T> 型のオブジェクトではなくて、どうしても DataTable 同士を結合したいということでも、多少書き方は変わりますが、やはり Linq to Objects で結合できます。

以前作ったサンプルを紹介しておきます。Microsoft が提供するサンプルデーターベース Northwind の Orders テーブル、Customers テーブルを DataTable に取得してそれらを結合しています。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Data.SqlClient; namespace ConsoleAppDataTableJoinByLinq { // 結合後の結果を格納するためのクラス定義 public class Result { public int OrderID { get; set; } public string CompanyName { get; set; } public int? EmployeeID { set; get; } public DateTime? OrderDate { get; set; } public decimal? Freight { get; set; } } class Program { static void Main(string[] args) { string connString = @"data source=lpc:(local)\sqlexpress;initial catalog=NORTHWIND;integrated security=True;"; string queryOrders = "SELECT [OrderID],[CustomerID],[EmployeeID],[OrderDate],[RequiredDate],[ShippedDate],[ShipVia],[Freight],[ShipName],[ShipAddress],[ShipCity],[ShipRegion],[ShipPostalCode],[ShipCountry] FROM [Orders]"; string queryCustomers = "SELECT [CustomerID],[CompanyName],[ContactName],[ContactTitle],[Address],[City],[Region],[PostalCode],[Country],[Phone],[Fax] FROM [Customers]"; DataTable orders = new DataTable(); DataTable customers = new DataTable(); using (SqlConnection connection = new SqlConnection(connString)) { using (SqlCommand command = new SqlCommand(queryOrders, connection)) { SqlDataAdapter adapter = new SqlDataAdapter(command); adapter.Fill(orders); } using (SqlCommand command = new SqlCommand(queryCustomers, connection)) { SqlDataAdapter adapter = new SqlDataAdapter(command); adapter.Fill(customers); } } // 内部結合 var innerJoin = from o in orders.AsEnumerable() join c in customers.AsEnumerable() on o.Field<string>("CustomerID") equals c.Field<string>("CustomerID") where o.Field<int?>("EmployeeID") == 9 select new Result { OrderID = o.Field<int>("OrderID"), CompanyName = c.Field<string>("CompanyName"), EmployeeID = o.Field<int?>("EmployeeID"), OrderDate = o.Field<DateTime?>("OrderDate"), Freight = o.Field<decimal?>("Freight") }; foreach (Result result in innerJoin) { Console.WriteLine($"Id: {result.OrderID}, Name: {result.CompanyName}, EmpID: {result.EmployeeID}, Date: {result.OrderDate}, Freight: {result.Freight}"); } Console.WriteLine("--------------------------------"); // 左外部結合 var leftOuterJoin = from o in orders.AsEnumerable() join c in customers.AsEnumerable() on o.Field<string>("CustomerID") equals c.Field<string>("CustomerID") into cGroup from item in cGroup.DefaultIfEmpty() // Empty だと item が null になる where o.Field<int?>("EmployeeID") == 9 select new Result { OrderID = o.Field<int>("OrderID"), CompanyName = (item == null) ? "N/A" : item.Field<string>("CompanyName"), // item.Field<string>("CompanyName") ?? "N/A" ではだめ EmployeeID = o.Field<int?>("EmployeeID"), OrderDate = o.Field<DateTime?>("OrderDate"), Freight = o.Field<decimal?>("Freight") }; foreach (Result result in leftOuterJoin) { Console.WriteLine($"Id: {result.OrderID}, Name: {result.CompanyName}, EmpID: {result.EmployeeID}, Date: {result.OrderDate}, Freight: {result.Freight}"); } } } }

投稿2020/11/10 03:44

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

AEGIL

2020/11/11 04:56

返信遅くなってしまい申し訳ございません。回答して頂いたものを参考にしてDataTable同士を結合するものではなく1から書き直しておりました。まだ、思うように動作ができておらず 回答内のselect new Resultの役割を教えていただいてもよろしいですか?
退会済みユーザー

退会済みユーザー

2020/11/11 05:29 編集

> 回答内のselect new Resultの役割を教えていただいてもよろしいですか? Result はコードのコメントにありますように「結合後の結果を格納するためのクラス」です。new で Result クラスのインスタンスを生成して、new Result { ... } の ... のコードで各プロパティに Linq の式で取得したデータを代入しています。select で取得したレコードの数だけそれを繰り返すので最終的に List<Result> 型のオブジェクトとして取得しています。
AEGIL

2020/11/11 07:44 編集

動作致しました。ありがとうございます。一応お聞きしたいのですが、どのサイトでもlinqが勧められていて処理速度もDataTableを結合するよりも早いと出ていました。上記の質問でのコードでの結合もしようとしたのですが、やはり面倒になりますか? //tableからバーコードのユニークリストをつくる  DataTable dtDistinct = ResultDT.DefaultView.ToTable(true, "Barcode"); //そのユニークリストを使ってSQLを書く DataRow[] dataRows = dtDistinct.Select(""); //オラクルにSQLを投げてOracleDTで受け取る //oracleDTとcsvDTをぶつけてtableに書き込む foreach (DataRow r in csvDt.Rows) { if(csvDt/*のカラム名*/ == oracleDT/*のカラム名*/) { } }
退会済みユーザー

退会済みユーザー

2020/11/11 08:04

DataTable が適材適所かとか、開発者の知識や開発チームの方針とか、開発工数と保守工数とかを総合的に判断して決める話だと思います。 昔ながらのアプリ、例えば WinForms + ADO.NET + DataGridView で DB の表示・編集・更新などを行うアプリとかでは DataSet / DataTable が適材適所と言えると思います。 新規開発であれば Linq to Entities / Objects を採用する方向に進むのが選択肢の一番に来るのではとは思いますが。
AEGIL

2020/11/11 08:08

なるほど。ご返答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問