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

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

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

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

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

Q&A

解決済

1回答

12463閲覧

C# データベースでデータ抽出時にメモリ不足を起こす。

TAKAYASU

総合スコア146

C#

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

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

0グッド

0クリップ

投稿2016/10/31 00:55

いつもお世話になってます。
10月からC#とSQLServerで検索や登録等のやり取りをする機会が出てきまして現在勉強しています。

C#

1 //select関数に下記情報を渡す。 2 //第一引数 string sql文 3 //第二引数 HashTable パラメータ 4 //第三引数 SqlConnection コネクション 5 public DataTable select(string sql, Hashtable prms = null, SqlConnection pconn = null) 6 { 7 SqlConnection objConn = pconn; 8 DataTable dataTable = null; 9 try 10 { 11 if (pconn == null) 12 { 13 /*** データベースに接続 ***/ 14 objConn = new SqlConnection(connection_str); 15 objConn.Open(); 16 } 17 18 //アダプタ作成 19 SqlDataAdapter daAuthors 20 = new SqlDataAdapter(); 21 22 daAuthors.SelectCommand = new SqlCommand(sql, objConn); 23 24 if (prms != null) 25 { 26 foreach (string key in prms.Keys) 27 { 28 //パラメータ格納 29 daAuthors.SelectCommand.Parameters.Add(new SqlParameter(key, prms[key])); 30 } 31 } 32 33 //データセット作成 34 DataSet dataSet = new DataSet(); 35 daAuthors.FillSchema(dataSet, SchemaType.Source, "DATA"); 36 37 //ここでエラーを吐く 38 daAuthors.Fill(dataSet, "DATA"); 39 40 //取得したデータを代入する。 41 dataTable = dataSet.Tables["DATA"]; 42 } 43 catch (Exception) 44 { 45 throw; 46 } 47 finally 48 { 49 if (pconn == null && objConn != null) 50 { 51 objConn.Close(); 52 } 53 } 54 return dataTable; 55 }

##問題点
上記コードで取得件数が1000件以上ある場合、2分以上経過したあたりからOutOfMemoryを吐き出してしまいます。

##知りたいこと
取得するデータ量が多く、メモリ不足を起こしてしまう場合
どのような対策を講じればよいのでしょうか?
コードよりも手法を知りたいです。

データベースはまだまだ勉強中の身ですので初歩的な質問かもしれませんがよろしくお願い致します!
不備等ありましたらご指摘の程お願い致します!

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

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

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

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

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

guest

回答1

0

ベストアンサー

一度に大量のデータをメモリに入れるとメモリリークしやすいので,クエリを複数に分けて一回あたりに持ってくるレコード数の単位を区切りながら実行したり,LazyLoadingという仕組みを使って逐次読み込みでレコードを取得しメモリを解放するようにする仕組みを作ることが多いです。全てのレコードをメモリに突っ込まなければできない処理は基本的にマシンスペックを上げるしかありません。

検索した所こちらの記事が引っかかりましたが,lazyload C#などで調べると色々出てくるので調べて見てください。

上の例はreturnで実装されていますが普通はyieldを使う実装が多いとおもいます。

投稿2016/10/31 01:03

編集2016/10/31 01:10
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

TAKAYASU

2016/10/31 01:20 編集

とてもわかりやすい回答ありがとうございます! >一度に大量のデータをメモリに入れるとメモリリークするので,クエリを複数に分けて一回あたりに持ってくるレコード数の単位を区切りながら実行したり,LazyLoadingという仕組みを使って逐次読み込みでレコードを取得しメモリを解放するようにする仕組みを作ることが多いです。 どうしようどうしようと考えていた時は 「別のクラスを使う」という方法しか思い浮かばず、そういうやり方があることを知りませんでした。 LazyLoadingも調べてみました、ためになる情報ありがとうございます! >上の例はreturnで実装されていますが普通はyieldを使う実装が多いとおもいます。 yieldですか・・・これまで使ったことがないのでまずはどういったものかを調べてみる必要がありそうです。。。 理解できたらyieldも使おうと考えてます! ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問