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

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

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

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

LINQ to SQL

LINQ to SQLは.NET Framework 3.5のコンポーネントで、リレーショナル データをオブジェクトとして管理するためのランタイム インフラストラクチャを提供します。

Visual Studio 2010

Microsoft Visual Studio 2010はMicrosoftが提供している統合開発環境(IDE)です。

Q&A

解決済

2回答

6188閲覧

【コード修正】DBへのアクセス回数を減らしたい

unyuho7

総合スコア7

C#

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

LINQ to SQL

LINQ to SQLは.NET Framework 3.5のコンポーネントで、リレーショナル データをオブジェクトとして管理するためのランタイム インフラストラクチャを提供します。

Visual Studio 2010

Microsoft Visual Studio 2010はMicrosoftが提供している統合開発環境(IDE)です。

0グッド

0クリップ

投稿2015/10/21 04:06

編集2015/10/21 04:13

###前提・実現したいこと
先週よりC#の勉強をしているプログラミング初心者です。
現在、VB2010にてとあるバッチプログラムを作成しています。
一度プログラム自体は完成したのですが、少しDBへのアクセス回数が多すぎるのでもっと少なく済む様にしたいと考えています。
考えとしては、最初に使うデータを全部持ってしまえば良いのではと考えていて
ループ内の「同一車輌SEQかつ同一計上年月の固定経費情報を取得」と「取得した固定経費情報をリスト化」しているコードをループの外に持って行きたいです。
###発生している問題・エラーメッセージ
T_FixedExpenseテーブルのTrailerSEQとM_TralierのTrailerSEQが一緒のものを絞り込むところで悩んでいます。
ループの外だとmtItemが使えないのはわかるのですが・・・。
###ソースコード

C#

1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //ログ出力のテキストファイルを開く 6 Encoding sjisEnc = Encoding.GetEncoding("Shift_JIS"); 7 StreamWriter writer = new StreamWriter(@"FixedExpenceEntry.Log", true, sjisEnc); 8 9 //バッチ起動時のログ出力 10 writer.WriteLine("[" + DateTime.Now + "]" + "FixedExpence Entry Start."); 11 12 //基本月額項目の定数を定義 13 const 14 int dep1 = 13; 15 int dep2 = 19; 16 int lease1 = 14; 17 int lease2 = 20; 18 int volIns1 = 10; 19 int volIns2 = 13; 20 int cargoIns1 = 10; 21 int cargoIns2 = 14; 22 int radio1 = 9; 23 int radio2 = 11; 24 int garage1 = 12; 25 int garage2 = 18; 26 int chaUse1 = 15; 27 int chaUse2 = 22; 28 29 //インスタンスの作成 30 ttedb_testEntities entity = new ttedb_testEntities(); 31 32 //DBから車輌情報を取得 33 { 34 IQueryable<M_Trailer> trailer = 35 from a in entity.M_Trailer 36 where 37 a.DeleteFlg == null && 38 a.WorkDiv == 1 && 39 ( 40 a.Depreciation != 0 || 41 a.Lease != 0 || 42 a.VoluntaryInsurance != 0 || 43 a.CargoInsurance != 0 || 44 a.Radio != 0 || 45 a.Garage != 0 || 46 a.ChassisUsage != 0 47 ) 48 select a; 49 50 51 //車両情報をリストに格納 52 List<M_Trailer> mtList = trailer.ToList(); 53 54 55 56 //トランザクション開始 57 58 using (var ts = new TransactionScope()) 59 { 60 try 61 { 62 //変数を宣言 63 string argsdate; 64 DateTime dtArgs; 65 DateTime dt; 66 67 //変数dtを実行日で初期化 68 dt = DateTime.Today; 69 70 //コマンドライン引数が指定されている時 71 if (0 != args.Length) 72 { 73 //コマンドライン引数を取得 74 string[] cmds = Environment.GetCommandLineArgs(); 75 argsdate = cmds[1]; 76 77 //取得した引数がDateTime型に変換できる時 78 if (DateTime.TryParse(argsdate, out dtArgs)) 79 { 80 //DateTime型に引数を変換 81 DateTime date = DateTime.Parse(argsdate); 82 dt = date; 83 } 84 //取得した引数がDateTime型に変換出来ない時 85 else 86 { 87 //エラーログを出力 88 writer.WriteLine("[" + DateTime.Now + "]" + "Parameter is not available."); 89 throw new System.ArgumentException("Parameter is not available"); 90 } 91 } 92 93 //月初日を定義 94 DateTime dateF = new DateTime(dt.Year, dt.Month, 1); 95 96 //月末日を定義 97 DateTime dateL = new DateTime(dt.AddMonths(1).Year, dt.AddMonths(1).Month, 1).AddDays(-1.0); 98 99 //固定経費データ出力開始時ログ出力 100 writer.WriteLine("[" + DateTime.Now + "]" + "Deta Create Start." + "[" + mtList.Count() + "]"); 101 102 //大ループ開始 103 foreach (var mtItem in mtList) 104 { 105 //同一車輌SEQ、計上年月の固定経費情報を取得 106 IQueryable<T_FixedExpense> sameExpense = from e in entity.T_FixedExpense 107 where e.TrailerSEQ == mtItem.TrailerSEQ && 108 e.AddUpMonth.Year == DateTime.Today.Year && 109 e.AddUpMonth.Month == DateTime.Today.Month 110 select e; 111 112 //取得した固定経費情報をListに格納 113 List<T_FixedExpense> tfeList = sameExpense.ToList(); 114 115 //運転手情報から車両情報に紐付いているDriverSEQを抽出 116 IQueryable<int> driver = from d in entity.M_Driver 117 where d.TrailerSEQ == mtItem.TrailerSEQ 118 select d.DriverSEQ; 119 120 //紐付かない場合はnull、紐付いている場合は一件取得する 121 int? driverseq = null; 122 123 if (driver.Count() > 0) 124 { 125 driverseq = driver.Single(); 126 } 127 128 //変数を定義 129 int expenseSEQ; 130 short rowSub; 131 132 //データーベースへ登録開始時ログ出力 133 writer.WriteLine("[" + DateTime.Now + "]" + "FDB Entry Start." + "[" + tfeList.Count() + "]"); 134 135 //固定経費データがない場合は新しく登録 136 if (tfeList.Count() == 0) 137 { 138 T_FixedExpense fe = new T_FixedExpense() 139 140 { 141 AddUpMonth = dateF, 142 TrailerSEQ = mtItem.TrailerSEQ, 143 DriverSEQ = driverseq, 144 CreateDatetime = DateTime.Now, 145 CreateUser = 2 146 147 }; 148 entity.AddToT_FixedExpense(fe); 149 entity.SaveChanges(); 150 151 expenseSEQ = fe.FixedExpenseSEQ; 152 153 rowSub = 1; 154 } 155 else 156 { 157 //抽出した固定経費データを1件取得(FixedExpenceSEQ) 158 expenseSEQ = tfeList.Single().FixedExpenseSEQ; 159 160 //取得した固定経費から詳細データの連番を取得 161 var row2 = from r in entity.T_FixedExpenseDetails 162 where r.FixedExpenseSEQ == expenseSEQ 163 select r.FixedExpenseRow; 164 165 //件数が0なら1 166 if (row2.Count() == 0) 167 { 168 rowSub = 1; 169 } 170 171 //件数が1以上なら連番の最後に+1 172 else 173 { 174 rowSub = (short)(row2.Max() + 1); 175 } 176 }

###補足情報(言語/FW/ツール等のバージョンなど)
ソースコードを全て載せると長すぎるのか投稿出来なかったので端折ってあります。

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

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

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

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

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

guest

回答2

0

ふと思ったんですが単純に別処理で「車輌SEQ別の年月毎の固定経費情報」を取得して「固定経費情報」のコレクション(Dictionary)として持っておけばよいような気がしますが、ボリューム感がわかりませんのでなんともですが...

投稿2015/10/22 01:59

dojikko

総合スコア3939

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

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

unyuho7

2015/10/22 23:51

ご教授ありがとうございます。 そこまで大規模なデータを処理するわけではないので、いただいた方法でプログラムを作ってみましたがデバッグ時に分かりやすいコードが出来ましてこれもまた良いなと感じました。 色々な考え方があってプログラミングは奥が深いです・・・。 ありがとうございました。
guest

0

ベストアンサー

cmds[1] が固定なので、コマンドラインパラメタの解析処理をmain先頭にいどうする。

最初のクエリが右、次のクエリが左の内部結合にすれば一発で全部取ってこれませんか。

linq の内部結合

https://msdn.microsoft.com/ja-jp/library/bb397941.aspx

今の実装だと最初のsql の実行結果の取得、次のsqlは、最初のsqlの実行結果に対して逐次問い合わせになるので効率よく無いですね。2つのクエリの接続先が異なるdbである場合は、
http://oshiete.goo.ne.jp/qa/6798209.html#bmb=1
こういうやり方もあるようです。

投稿2015/10/21 05:10

ipadcaron

総合スコア1693

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

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

unyuho7

2015/10/22 23:48

ご教授ありがとうございます。 お答えいただいた方法で無事動作テストまで完了いたしました。 プログラムの実行速度も早くなり、またひとつ理解が進んだと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問