Blog ブログ

へっぽこプログラマの奮闘記 ~第1回:データベースが更新されません~


皆様 初にお目にかかります、新人プログラマの田中 智大と申します。
技術に関してはまだまだへっぽこですが、先輩方の助力をいただきながら日々努力を重ね成長しております。

さて、今回はC#のEntity FrameworkのSystem.Data.Entity.DbSet<TEntity>を使っている時に失敗した事について書いていきたいと思います。
やりたかった事は「データベースに指定したIDのデータが存在した場合は上書き。無ければ新たにレコードを新規作成する」という事です。その時のコードを再現したものをどうぞご覧ください。

このcreate()メソッドを呼び出してSaveChanges()を行うとデータベースの値が新規作成or上書きされるはずでした。
ところが、いざ動かすと「値が更新されない!!!」という事態に陥ってしまいました。。。(ちなみにDBへのレコード追加は普通にできていました)

さて、なぜ今回こんな事が起きてしまったかというと、実はこのコードは「更新の処理でDBのデータへの参照を思いっきり上書きしている」コードなので更新できなかったのです。
どういう事かを図と合わせてもう少し詳しく説明しましょう。

そもそも Entity Framework の DbSet<TEntity> は「データベースに対してクエリを発行し、その結果をメモリに保持する」動きをします。今回のコードでは26,27行目でその処理を行っています。
実はこのメモリに保持されたデータはAdded(追加)、Unchanged(変更なし)、Modified(変更あり)の3種類の状態を持っています。

データベースからデータを取得する際、Unchangedの状態で結果をメモリに保持します。
データに変更を加えると状態はModifiedに変わり、Addメソッドを使ってレコードを追加するとAddedの状態に変わります。
SaveChanges()が呼ばれた時に初めてModifiedの状態のものは変更され、Addedのものはレコードが追加されるようになるのです。

そして今回の失敗はメモリにせっかく確保したデータベースのデータの参照をnewしたデータの参照で上書きをしてしまったため、データベースのデータはUnchangedの状態のまま変わる事がなく、結果データベースの値がSaveChanges()を呼び出しても更新されないという事態が発生してしまったものです。

サーバーのプログラムはこんな感じの動きをしています↓

じゃあ、このコードはどうやったら値を更新してくれるのかといいますと、

こうすることでメモリに保持されているデータに変更が加わり、Modifiedの状態になるので、SaveChanges()を呼び出すと値が正常に更新されるようになります。

まとめ

Entity Framework がどうやって動いているかを知らないと、こんなミスを起こしてしまうんですね。。。
まだまだわからない事がたくさんあり、今後多くの壁にぶち当たっていくことにはなると思いますが、たくさん勉強して少しでも早く先輩社員に追いついて、一人前のプログラマになるべく、これからも奮闘して参ります。
長くなりましたが、これからもどうぞよろしくお願いします。



採用情報

クラウドクリエイティブスタジオではエンジニアの方を絶賛募集中です。
皆さんとともに、是非!良きゲームを作っていきたいと思っております!