Azureはじめました

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

EntityFrameworkで出力されるクラスにKeyアノテーションを追加する

別件の仕事で2ヶ月近く離れてたけどそろそろこっちに復帰。

EFで出力されるモデルをMVC4あたりで使おうとした場合で、プライマリキーが"id"でない場合はKeyアノテーションを付けて明示的にキーを指定してやる必要があるようだ。

ところが、EFのデータベースからモデルを作成してるとモデルクラスは自動作成されるので一々手で修正しなきゃならんのは何とかならんかと調べてみた。


Data Annotations in T4 templates

I've worked this one out myself. See below:

// SDC 19th April 2011
// Identify a primary key 
bool isPrimaryKey = ef.IsKey(edmProperty);
#>

<#
if (isPrimaryKey)
  {
#>
  [Key]
<#
  }
#>
<#=PropertyVirtualModifier(Accessibility.ForProperty(edmProperty))#> <#=code.Escape(edmProperty.TypeUsage)#> <#=code.Escape(edmProperty)#>

entity framework - EDMX is overwriting Key data annotations - Stack Overflow

You could update your T4 template to add in the data annotation for you on primary keys?

if (simpleProperties.Any())
{
    foreach (var edmProperty in simpleProperties)
    {
     if (ef.IsKey(edmProperty)){
#>
[Key]
<# } #>

やっぱり似たようなこと考えてる人いるようで、中はどちらもT4テンプレートで治すって事らしいのでやってみる。

T4テンプレートを修正

edmxファイルを開くと中にT4テンプレートが2つあって治すのは.ttの方
f:id:twisted0517:20130909151021p:plain

治すべき箇所は2種類3箇所。

Keyアノテーション出力

Keyアノテーションを出力するのはキーのプロパティを出力している箇所の直前になる。
ソースを"edmProperty in simpleProperties"で検索すると2箇所あるのでそこを修正する。(69行目付近、152行目付近)

        foreach(var edmProperty in simpleProperties)
        {
#>
	<# if (ef.IsKey(edmProperty)){ #> 
	[Key]
	<# } #>
    <#=codeStringGenerator.Property(edmProperty)#>
using出力

KeyアノテーションはSystem.Componentmodel.DataAnnotationsなので、これがUsingに含まれていないとコンパイルエラーとなるのでUsing出力部分を修正
usingを出力しているのは同じT4テンプレートのUsingDirectives()の部分。

    public string UsingDirectives(bool inHeader, bool includeCollections = true)
    {
        return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
            ? string.Format(
                CultureInfo.InvariantCulture,
                "{0}using System;{1}" +
                "{2}",
                inHeader ? Environment.NewLine : "",
                (includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "")
					+Environment.NewLine +"using System.ComponentModel.DataAnnotations;",
                inHeader ? "" : Environment.NewLine)
            : "";
    }

string.formatの第3引数に追加した。

出力してみる

edmxの「データベースからモデルを更新」でモデルを再出力。

namespace MVCTest.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    public partial class UserProfile
    {
        public UserProfile()
        {
            this.webpages_Roles = new HashSet<webpages_Roles>();
        }
    
    		[Key]
    	    public int UserId { get; set; }
    	    public string UserName { get; set; }
    
        public virtual ICollection<webpages_Roles> webpages_Roles { get; set; }
    }
}

ちゃんとKeyアノテーションが出力された。
おっけー。