2009-06-26 19 views
24

C'è un modo per aggiungere attributi personalizzati alle proprietà nel codice generato da EF? L'unica cosa che posso vedere come soluzione plausibile sarebbe quella di creare un modello T4 personalizzato. Tuttavia, a causa della natura dell'attributo, sarebbe impossibile determinare il parametro dell'attributo corretto per ogni proprietà EF.Aggiunta di attributi di proprietà personalizzati nel codice Entity Framework

risposta

35

È possibile eseguire questa operazione specificando un tipo di metadati che rispecchia le proprietà e viene utilizzato semplicemente per l'attribuzione.

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

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

blog Steve Smith su di esso here.

Sfortunatamente l'approccio di cui sopra è fragile per il refactoring. Un'altra opzione è usare le nuove entità POCO. Questi evitano del tutto la generazione di codice compilato per quanto posso dire. Non li ho ancora usati, quindi non posso commentare eventuali insidie ​​o compromessi.

+0

Mi stavo innamorando di EF quando improvvisamente mi sono reso conto che gli attributi delle mie entità sarebbero stati praticamente inesistenti a causa del modo in cui sono gestiti. Grrrr. – Chev

+4

Riflettendo, 'assembly.GetType (typeof (Dinner) .ToString(). GetProperties()', 'property.Attributes' è null e' property.GetCustomAttributes (typeof (RequiredAttribute)) 'restituisce una matrice di lunghezza zero - dovrebbe uno riflette Dinner_Validation o è qualcos'altro? – lukiffer

0

Non credo che tu possa. Il generatore dichiara tutte le classi come parziali, permettendoti di estenderlo, ma non ti permetterà di contrassegnare le proprietà con attributi personalizzati dato che semplicemente genererà su di esse. L'unica cosa che puoi fare è scrivere le tue entità.

+0

Questo può essere stato il caso, ma ci sono alcune opzioni al giorno d'oggi. Vedi la mia risposta per informazioni. –

8

È possibile creare un'interfaccia e dichiarare l'attributo sull'interfaccia.

partial class Person : IPerson {} 

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

Come nota a margine per i futuri lettori, questo * non * funziona con la convalida di asp.net-mvc. –

11

È possibile aggiungere questo al file di EDMX, con Designer anche:

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

e sostituire 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))); 
} 

Con:

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

Soluzione piacevole ... – Omtara

+0

HI, come cambio il modello T4? creato un file Model1.tt e tutto il suo testo è nero e sembra un'altra sintassi. – pungggi

2

è possibile aggiungere questa al file EDMX, con Designer anche:

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

e sostituire 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))); 
} 

Con:

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))); 
} 

E per Entity Framework 6, sostituire

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))); 
} 

con

public string Property(EdmProperty edmProperty) 
{ 
    var description = String.Empty; 
    bool isAttribute = false; 

    if(edmProperty.Documentation != null && 
     string.IsNullOrWhiteSpace(edmProperty.Documentation.Summary) == false) 
    { 
     string summary = edmProperty.Documentation.Summary; 
     if (!String.IsNullOrEmpty(summary) && summary.First() == '[' && summary.Last() == ']') 
     { 
      isAttribute = true; 
     } 

     if (isAttribute) 
     { 
      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); 
     } 

    } 

    return string.Format(
     CultureInfo.InvariantCulture, 
     "{5}{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)), 
     description); 
} 

Avvertenze:

  • namespace devono essere risolti in modo assoluto.
  • Assume attributi iniziano con '[' e terminano con ']' - nessun altro controllo di errore
  • Se un'apertura e parentesi graffa di chiusura non viene trovato, il riepilogo delle proprietà Entity Framework è avvolto in una tripla commento barra XML.
  • Tenta di abbinare le informazioni di stile di visualizzazione visive predefinite (in realtà solo i trattini) che possono o meno essere il caso per il tuo progetto. Questo include nuove linee.Uscita

campione:

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

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

Oltre alla risposta di BurnsBA, Per applicare questo alle proprietà di navigazione troppo, aggiornare NavigationProperty() così:

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); 
} 

Io lo uso per aggiungere [Newtonsoft.Json.JsonIgnore] al mio proprietà.

Nota: è necessario aggiungere questi per <...>Model.tt e non <...>Model.Context.tt

Problemi correlati