blog.ishinao.net

1111月/11

ADO.NET Entity Frameworkで自動生成されたモデルクラスを拡張する方法

ADO.NET Entity Frameworkで自動生成されたモデルクラスを拡張する方法はあるんだろうか? Foo.edmxに対応するFoo.Designer.csファイルは、Foo.edmxファイルをいじると自動的に上書き再生成されてしまうんで、直接そのファイルを変更することはできない。

でも、データ処理がらみの機能を実装する場合、別クラスを作ってそちらで書くのではなく、モデルクラスの方を直接いじってそちらで拡張した方が直観的な設計になることも多いよね。

で、Foo.Designer.csファイルの中身をよく見てみたら、モデルクラスはpartialで定義されていた。ってことは別ファイルにpartialで追加メソッドを用意すればいいだけなのか。たとえば、barテーブルに対応するBarクラスにメソッドを追加したければ、適当なクラスファイルを用意して、


public partial class Bar : EntityObject
{
    public string ExtendedMethod()
    {
        return "extended!";
    }
}

とかでOK。

これで機能拡張はできるとして、標準的な操作をoverrideしたりはできないのかな? たとえばinsert、update時にはcreated_at、modified_atとかを自動で更新したりとか。

調べてみたところ、EntityObjectにはPropertyChangedというイベントがあるので、それをフックすれば良さそう。


public partial class Bar: EntityObject
{
    public Bar() : Base()
    {
        PropertyChanged += OnPropertyChanged;
    }

    protected void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (new string[]{"updated_at", "created_at"}.Contains(e.PropertyName)) return;
        if (id == 0) {// primary keyがセットされていない=新規作成
            created_at = DateTime.Now;
        }
        updated_at = DateTime.Now; 
    }
}

一応なんてコードでそれっぽく動いている。新規作成 or 更新の区別をid == 0かどうかで識別しているのが妥当かどうかはちょっと怪しい。ほかにもっとちゃんとした方法はないかな。

EntityStateってのを使うとそれっぽいことができそう。オブジェクトの作成・更新・削除状態が取得できるプロパティの模様。と思ったが、これはオブジェクトコンテキストにAttachされていないと状態が取得できないのか。

EntityObjectインスタンスメソッドのスコープからは親オブジェクトコンテキストが見えないから、いったんAttachして確認することもできないし、副作用もありそうだからあまりやりたくもないなー。ひとまずはidを見て切り分けることにしておくか。

関連する投稿:

    None Found

Filed under: 技術日記 Comments Off