記事内に広告が含まれています

【ワレコのEntity Framework】最近覚えた小技

この記事は約6分で読めます。
スポンサーリンク

写真 Entity Frameworkを勉強中のIT女子

ワテの場合、Entity Framework無しではデータベースプログラミングが出来なくなって来た。

従来は、生のSQLコマンドを文字列で作成して実行する手法を多用していたのだが、最近では、そんなローレベルな手法は滅多に使わない。

使うのはEntity FrameworkのCode Firstだ。

さて、そんなワテが最近覚えた手法の備忘録。

まあ、Entity Frameworkをやっているなら誰でも知っていると思うが、ワテは知らなんだ。

スポンサーリンク
スポンサーリンク

EFでWhere条件に一致したレコードに変更を加える処理

Where条件で絞り込んだ複数のレコードに対して変更を加えたい。

例えば、以下のようなC#コードを書けば良い。

using (var context = new WatenoDbContext())
{
    // 更新対象の要素を取り出す
    var result = context.WatenoModels.Where(r => r.name == "ワテ").ToList();

    // それぞれの要素を更新する
    foreach (r in result)
    {
        r.personality = "無責任男";
    }

    // DBを更新する
    context.SaveChanges();
}

要するに、Where条件に一致するレコードを全部取り出す。

そのレコードに対して、何らかの変更を加えてからデータベースを更新したい場合だ。

 

そう言う場合には、ToList()化しておいてforeachでループ処理で回せば良い。

必要に応じてLINQでも良いだろう。

ワテの場合、FirstOrDefault()で取得した単一のレコードに対してなら、この手の変更処理は良くやっていたのだが、Whereで取り出した複数のレコードに対しての変更作業は、今回初めてやった。

この手法で上手く行った。

ちなみに .ToList() しないとエラーするのだ。

理由は知らない。

forループの中でSaveChange()すると例外が出る場合の対策 .ToList()

例えば、where条件にマッチしたレコードに対して、何らかの変更処理を行う。

そのforループ処理が全て完了したら、ループを脱出してSaveChange()するのが普通のやり方だ。

using (var context = new WatenoDbContext()) {
   var result = context.WatenoModels.Where(r => r.name == "ワテ")
   foreach( var item in result )
   { 
      //... 何らかの処理
   }
    context.SaveChanges(); 
}

ループを脱出したら一回だけSaveChange() する普通のコード

 

でも例えば、レコードが1万件くらいあり、「何らかの処理」の部分が複雑で、一件の処理に数秒掛る場合、全件のループが完了するのは

  数秒x1万 = 数万秒 = 数時間

となる。

そんなループが完了した時点で一回だけSaveChange() すれば良いのだが、でもループの中で例外が出て異常終了する場合もある。

そうなると、数時間掛かりで計算した変更がSaveChange() を一回も実行する前に終わってしまう。

そんな状況を避けたいので、ループの中で毎回DBにSaveChange() する案を思い付く(下のコード)。

でも、このコードは例外が出るのだ。

using (var context = new WatenoDbContext()) {
   var result = context.WatenoModels.Where(r => r.name == "ワテ")
   foreach( var item in result )
   {
      //... 何らかの処理
      context.SaveChanges();
   }
}

ループの中でSaveChange()すると例外が出る例

 

まあ、例外が出る理由は良く知らない。

ここに似たような議論を見付けたので興味ある人は読んでみると良いだろう。

Any difference between calling SaveChanges() inside and outside a foreach loop?
Is there any performance benefit/technical differences between calling EF SaveChanges() in a foreach loop or outside a l...

Any difference between calling SaveChanges() inside and outside a foreach loop?

 

さて、ループの中でSaveChange()しても例外を出さないようにするには .ToList() を付ければ良い。

using (var context = new WatenoDbContext()) {
   var result = context.WatenoModels.Where(r => r.name == "ワテ").ToList();
   foreach( var item in result )
   {
      //... 何らかの処理
      context.SaveChanges();
   }
}

ループの中でSaveChange()しても例外を出さないようにするには .ToList() を付ける

 

取り敢えず、このように .ToList() してやれば無事に成功した。

まあ、.ToList() の有無で何故挙動が変わるのかなど、詳しい事が分ったらここに追記したい。

文字列がNULLかどうかの判定

SQL文の物凄く基本的な事だが、文字列型のカラム[名前]に対して、空文字列のレコードのみ取り出すには、

where [名前]  = ''

だ。

 

一方、[名前]がNULL許容型の場合、NULLが入っている場合もある。

[名前]がNULLのレコードのみ取り出したい場合には、

where [名前] = NULL
や
where [名前] = 'NULL'

これは駄目だ。

正しくは、

where [名前] is NULL

となる。

 

まとめ

まあ、ワテの場合、Entity Frameworkの1パーセントも理解出来ていないし、使いこなせていない。

 

Entity Framework Core in Action

三番目の本は有名な山田さんの本だ。

ちなみに、ワテは読んでいない。

あかんがな。

スポンサーリンク
コメント募集

この記事に関して何か質問とか補足など有りましたら、このページ下部にあるコメント欄からお知らせ下さい。

C#Entity Framework
スポンサーリンク
シェアする
warekoをフォローする
スポンサーリンク

コメント