partialクラスで自動生成コードによる上書きを回避する方法

enfity framework(EF)でデータベースファーストを利用していると、
モデルが上書きされて、記載したコードが消えてしまうといったことはないでしょうか。

上書きされない方法をお探しの方向け記事です。

自動生成されたコードに、データベースに関係ないプロパティの追加や
モデルに関連したメソッドを実装する方法について紹介します。

partialクラスで自動生成コードによる上書きを回避する方法

まずは結論から、

  • 自動生成されたコードに上書きされないためにはpartialクラスを利用する

です。

C#には一つのクラスを複数のファイルに記載できる機能partialがあります。

partialを利用すればenfity frameworkで再生成してもコードが消えることはありません。

entity frameworkの自動生成はファイル名とリンクしている

例えば次のようなテーブルをデータベースファーストで生成したとしましょう。

studentテーブル

カラム名
student_idint
namenvarchar(50)
ageint

このstudentテーブルをEntity Framework でコード化すると、

自動生成されたコードは生成もとになっているテーブルとファイル名が紐づきます。

このため、いつでも同じテーブルの変更を同じCSファイルに行ってくれるので、更新漏れの心配はないでしょう。

自動生成したコードを編集しないのであれば、とくに問題はないですね。

しかし、手動でコード修正するときには課題になります。

テーブルが更新されるたびに、自分で書いたコードが消えることになりますので、

同じファイルに自前のコードを記載してしまうと、再生成時にどうやっても上書きされてしまうのです。

別のファイルに分けて定義できるparitalクラス

定義したいメソッドやプロパティを削除されないためには、

別のファイルに記載してしまえば、可能ですね。

そこでpartialクラスの出番。

一つのクラスを別々のファイルで定義する機能をこのpartialクラスは持っています。

実際の例を記載します。

自動生成されたStudentクラスはStudent.csファイルに記載されているので、

別のファイルとしてStudentEx.csファイルを用意し、自分で追加したいコードをStudentクラスに書くことができます。

このように、2つのファイルに分けることで、

片方は上書き更新できるように、
もう片方は上書きされないように管理することができるのです。

この別々のファイルで管理をすることができるのがpartialクラス=部分クラスという仕組みです。

partialクラスの書き方

partialクラスの書き方はこちら。

  • 関連がわかる別名のファイルを用意しよう
  • 同じ名前空間に配置しよう
  • paritalキーワードをつけてクラス名をそろえよう

partialクラスにするのは難しくありません。ポイントをさらっと確認していきましょう

関連がわかる別名のファイルを用意しよう

entity frameworkで自動生成されるファイルはテーブル名になっています。

partialで別ファイルに定義するときは、どんなファイル名でもOKなのですけれども、
自動で作られたファイルと関連がわかるように類似のファイル名にしてあげると良いと思います。

今回紹介している例は末尾にExとだけつけています。

もし、ファイル名に悩むようであれば、参考にしてみてください。

同じ名前空間に配置しよう

partialクラスは、コンパイルするときには、複数のファイルを結合させて、ひとつのクラスされます。

それゆえ、partialクラスは複数のファイルに定義することはあっても、

すべて同じ名前空間に定義する必要があります

ここで、名前空間が違うと完全に別のクラスとして扱われるので、注意しましょう。

paritalキーワードをつけてクラス名をそろえよう

別々のファイルで同じクラスを定義するには

partialキーワードをつけた同じ名前のクラスが必要になります。

別ファイルで定義したプロパティには[NotMapped]属性を使おう

テーブルに存在しないプロパティを追加したのであれば[NotMapped]を追加しましょう。

手動でコード追加するpartialクラスを定義できたら後は好きにコーディングして問題ないのですが、

プロパティを新たに追加する場合は注意が必要です。

というのも、

entity frameworkで自動生成したクラスはテーブルと密接に紐づいているので、
プロパティ名はテーブルの列名と紐づきます。

もし、テーブルに存在しないプロパティを定義してしまうと、「存在しないカラムです」とエラーが発生します。

Microsoft.Data.SqlClient.SqlException: ‘列名 ‘ExProperty’ が無効です。’

そこで、データベースと紐づけないように[NotMapped]をつけてことでエラー回避する必要があるのです。

ちなみに、[NotMapped]はこちらの名前空間にあります。

using System.ComponentModel.DataAnnotations.Schema;

partialクラスは自動生成されるコードと相性が良い

自動生成されたコードを拡張する場合は、

partialクラスの機能で別ファイルで記載することをお勧めします。

C#で開発していると、コードを自動生成してくれる仕組みに出会うでしょう。

entity frameworkもその一つですね。

ほかにもWindowsフォームなどもコードを自動生成する仕組みが備わっていて、

Windowsフォームにおいても、自動生成されたクラスはpartialクラスで定義が利用されています。

理由は、entity frameworkと同じで、自動生成は常にコード上書きの可能性があるからです。

自動生成する側は、利用者が拡張しやすいように、
あえてpartialクラスでコード生成してくれているので、
我々は、コードを追加するときにparialクラスの仕組みを使えばよいというわけです。

まとめ

今回のまとめに入ります。

  • 自動生成でコードを上書きされないためにpartialクラスを利用しよう
  • テーブルと関係ないプロパティを追加するときはNotMapped属性を使おう
  • entity framework以外にも自動生成コードではpartialクラスが利用できる

partialクラスの機能で上書きの悪夢からさよならしましょう。

では。