2009-06-26 9 views
24

EF生成コードのプロパティにカスタム属性を追加する方法はありますか?私がもっともらしい解決策として見ることができるのは、カスタムのT4テンプレートを考え出すことだけです。ただし、属性の性質上、EFプロパティごとに正しい属性パラメータを決定することは不可能です。Entity Frameworkコードにカスタムプロパティ属性を追加する

答えて

35

これは、プロパティを反映するメタデータタイプを指定することで可能になり、単に属性に使用されます。それhereについて

[MetadataType(typeof(Dinner_Validation))] 
public partial class Dinner 
{} 

public class Dinner_Validation 
{ 
    [Required] 
    public string Title { get; set; } 
} 

スティーブ・スミスのブログ。

残念ながら、上記のアプローチはリファクタリングにとって脆弱です。別のオプションは、新しいPOCOエンティティを使用することです。これらはコンパイル時のコード生成を私が知る限り避けています。私はまだそれらを使用していないので、どんな落とし穴やトレードオフについてもコメントすることはできません。

+0

私は、EFと恋に落ちていました。自分のエンティティの属性が、扱い方によっては事実上存在しないと突然気付きました。 Grrrr。 – Chev

+4

これを反映すると、 'assembly.GetType(typeof(Dinner).ToString().GetProperties()'、 'property.Attributes'はnullであり、' property.GetCustomAttributes(typeof(RequiredAttribute)) 'は長さゼロの配列を返します。 1つはDinner_Validationを反映しているのですか?他の何かが間違っていますか? – lukiffer

0

私はあなたができるとは思わない。ジェネレータはすべてのクラスを部分的に宣言して拡張することができますが、カスタム属性でプロパティをマークすることはできません。あなたができることの1つは、あなた自身のエンティティを書くことです。

+0

。情報については私の答えを見てください。 –

8

インターフェイスでインターフェイスを作成し、属性を宣言することができます。

partial class Person : IPerson {} 

public interface IPerson 
{ 
    [Required] 
    string Name { get; set; } 
} 
+2

今後の読者のためのメモとして、これはasp.net-mvcの検証では機能しません。 –

11

あなたはまた、デザイナーで、EDMXファイルにこれを追加することができます。

<Property Name="Nome" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" > 
      <Documentation> 
       <Summary>[MyCustomAttribute]</Summary> 
      </Documentation> 
</Property> 

をして交換T4:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty) 
{ 
    WriteProperty(Accessibility.ForProperty(edmProperty), 
        code.Escape(edmProperty.TypeUsage), 
        code.Escape(edmProperty), 
        code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 
        code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 
} 

付:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty) 
{ 
    if(edmProperty.Documentation != null && string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false) 
    { 
    #> 
    <#=edmProperty.Documentation.Summary#> 
<#+ 
    } 
    WriteProperty(Accessibility.ForProperty(edmProperty), 
        code.Escape(edmProperty.TypeUsage), 
        code.Escape(edmProperty), 
        code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 
        code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 
} 
+0

素敵な解決策... – Omtara

+0

Model1.ttファイルを作成し、そのすべてのテキストは黒で、別の構文のように見えます。 – pungggi

2

あなたはこれを追加することができますEDMXファイル、デザイナーの場合:

<Property Name="Nome" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" > 
      <Documentation> 
       <Summary>[MyCustomAttribute]</Summary> 
      </Documentation> 
</Property> 

とT4を置き換える:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty) 
{ 
    WriteProperty(Accessibility.ForProperty(edmProperty), 
        code.Escape(edmProperty.TypeUsage), 
        code.Escape(edmProperty), 
        code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 
        code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 
} 

付:

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty) 
{ 
    if(edmProperty.Documentation != null && string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false) 
    { 
    #> 
    <#=edmProperty.Documentation.Summary#> 
<#+ 
    } 
    WriteProperty(Accessibility.ForProperty(edmProperty), 
        code.Escape(edmProperty.TypeUsage), 
        code.Escape(edmProperty), 
        code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 
        code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 
} 

そして、Entity Frameworkの6のために、

public string Property(EdmProperty edmProperty) 
{ 
    return string.Format(
     CultureInfo.InvariantCulture, 
     "{0} {1} {2} {{ {3}get; {4}set; }}", 
     Accessibility.ForProperty(edmProperty), 
     _typeMapper.GetTypeName(edmProperty.TypeUsage), 
     _code.Escape(edmProperty), 
     _code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 
     _code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 
} 

を置き換えます3210の

警告:

  • 名前空間は絶対に解決する必要があります。
  • 属性で始まる「[」で終わる「]」と想定 - 他のエラーは、開閉括弧が見つからない場合は、エンティティフレームワークのプロパティの概要は、XMLトリプルスラッシュコメントに包まれ
  • をチェックしません。
  • あなたのプロジェクトではそうかもしれないし、そうでないかもしれないデフォルトのビジュアルスタジオスタイリング情報(本当にインデントされているもの)にマッチしようとします。これには新しい行が含まれます。

サンプル出力:BurnsBAの回答に加えて、

/// <summary> 
/// content type 
/// </summary> 
public System.Guid ContentType { get; set; } 

[System.ComponentModel.DisplayName("Last Modified")] 
public System.DateTime LastModified { get; set; } 
0

、あまりにナビゲーションプロパティにこれを適用するには、同様NavigationProperty()を更新:

public string NavigationProperty(NavigationProperty navProp) 
{ 
    var description = String.Empty; 
    if(navProp.Documentation != null && string.IsNullOrWhiteSpace(navProp.Documentation.Summary) == false) 
    { 
     string summary = navProp.Documentation.Summary; 
     if (!String.IsNullOrEmpty(summary) && summary.First() == '[' && summary.Last() == ']') 
     { 
      description = String.Format("\r\n\t{0}\r\n\t", summary); 
     } 
     else 
     { 
      description = String.Format("\r\n\t/// <summary>\r\n\t/// {0}\r\n\t/// </summary>\r\n\t", summary); 
     } 
    } 

    var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType()); 
    return string.Format(
     CultureInfo.InvariantCulture, 
     "{5}{0} {1} {2} {{ {3}get; {4}set; }}", 
     AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)), 
     navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, 
     _code.Escape(navProp), 
     _code.SpaceAfter(Accessibility.ForGetter(navProp)), 
     _code.SpaceAfter(Accessibility.ForSetter(navProp)), 
     description); 
} 

私は私に[Newtonsoft.Json.JsonIgnore]を追加するためにこれを使用プロパティ。

注:これはケースであったかもしれないが、いくつかのオプションが今日である<...>Model.ttにこれらを追加する必要がないと<...>Model.Context.tt

関連する問題