Azureはじめました

Windows Azureで業務システムを組んでみる日記

EntityFrameworkで出力されるクラスにDataAnnotationを設定する

前の記事では固定で使用されるKeyアノテーションをT4テンプレートを修正する形で追加したけど、RazorViewでの項目チェックに使うアノテーションなどは一概にテーブルから生成するわけにはいかないのでどうしたもんかと。

そこでモデルクラスがpartialであることを利用して別ファイル側で定義してやればいいじゃんと。

元のクラス

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    public partial class Person
    {
    	    [Key]
    	    public int id { get; set; }
    	    public string FirstName { get; set; }
    	    public string LastName { get; set; }
            public string Phone { get; set; }
    }

に対して

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    public partial class Person
    {
            [Required]
    	    public string FirstName { get; set; }
            [Required]
    	    public string LastName { get; set; }

            [Required(ErrorMessage="Please enter your valid phone number")]
            [RegularExpression("[0-9]{2,4}\\-[0-9]{1,4}\\-[0-9]{3,4}",ErrorMessage="電話番号の入力がおかしい")]
            public string Phone { get; set; }
    }

みたいな。

が、

The type 'Person' already contains a definition for 'FirstName'	

(;´д`) まぁそりゃそうだ。

検索したら見つかった

おんなじことで悩んでる人やっぱりいた。

Looks like I figured out a different way similar to the link above using MetadataTypeAttribute:

namespace MyApp.BusinessObjects
{
    [MetadataTypeAttribute(typeof(SomeClass.Metadata))]{
    public partial class SomeClass
    {
        internal sealed class Metadata
        {
            private Metadata()
            {
            }

            [Required]
            public string Name{ get; set; }
        }
    }
}

MetadataTypeAttributeでモデルクラスのメタデータを上書きするのか。

MetadataTypeAttribute 属性を使用することにより、クラスをデータ モデル部分クラスに関連付けることができます。 この関連クラスで、データ モデルにない追加のメタデータ情報を指定します。
たとえば、関連クラスでデータ フィールドに RequiredAttribute 属性を適用できます。 これにより、この制約がデータベース スキーマで規定されていなくても、そのフィールドの値が必ず指定されるようになります。

MetadataTypeAttribute 属性を次のように使用します。

  • アプリケーション内に、変更するデータ モデル部分クラスの入ったファイルを作成します。
  • 関連メタデータ クラスを作成します。
  • 部分エンティティ クラスに MetadataTypeAttribute 属性を適用し、関連クラスを指定します。

この属性を適用する場合は、次の使用上の制約に従う必要があります。

  • この属性はクラスにのみ適用できます。
  • この属性を派生クラスに継承することはできません。
  • 属性は 1 回しか適用できません。

という訳で拡張側を修正。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
   [MetadataTypeAttribute(typeof(Person.Metadata))]
    public partial class Person
    {
        internal sealed class Metadata {
            private Metadata() { }

[Required]
    	    public string FirstName { get; set; }
            [Required]
    	    public string LastName { get; set; }

            [Required(ErrorMessage="Please enter your valid phone number")]
            [RegularExpression("[0-9]{2,4}\\-[0-9]{1,4}\\-[0-9]{3,4}",ErrorMessage="電話番号の入力がおかしい")]
            public string Phone { get; set; }
        }
            
    }


なるほど面白い。