2011-10-01 7 views
18

Sto utilizzando EF 4.1 e cercavo una soluzione alternativa per la mancanza di supporto enum. Una proprietà di supporto di int sembra logica.mappatura codice struttura entità entità privata prima

[Required] 
    public VenueType Type 
    { 
     get { return (VenueType) TypeId; } 
     set { TypeId = (int) value; } 
    } 

    private int TypeId { get; set; } 

Ma come posso rendere privata questa proprietà e comunque mapparla. In altre parole:

Come si può mappare una proprietà privata utilizzando prima il codice EF 4.1?

+0

Posso aggiungere che EF supporta i setter privati, quindi almeno è possibile evitare l'impostazione Typ eId da fuori dalla tua classe. –

risposta

10

non è possibile prima mappare proprietà private nel codice EF. Puoi provare a cambiarlo in protected e configurarlo in una classe ereditata da EntityConfiguration.
Modifica
Ora è cambiato, si veda questo https://stackoverflow.com/a/13810766/861716

+16

volte cambiano-è possibile ora, vedere http://stackoverflow.com/a/13810766/861716 –

+0

Oltre all'osservazione di @ Gert, ho notato empiricamente in EF5 che le proprietà pubbliche con i setter privati ​​mappano correttamente con le prime convenzioni del codice predefinito. –

64

Ecco una convenzione è possibile utilizzare in EF 6+ per mappare le proprietà non pubblici selezionati (basta aggiungere l'attributo [Column] a una proprietà).

Nel tuo caso, devi cambiare TypeId a:

[Column] 
    private int TypeId { get; set; } 

Nella tua DbContext.OnModelCreating, è necessario registrare la convenzione:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Add(new NonPublicColumnAttributeConvention()); 
    } 

Infine, ecco la convenzione:

/// <summary> 
/// Convention to support binding private or protected properties to EF columns. 
/// </summary> 
public sealed class NonPublicColumnAttributeConvention : Convention 
{ 

    public NonPublicColumnAttributeConvention() 
    { 
     Types().Having(NonPublicProperties) 
       .Configure((config, properties) => 
          { 
           foreach (PropertyInfo prop in properties) 
           { 
            config.Property(prop); 
           } 
          }); 
    } 

    private IEnumerable<PropertyInfo> NonPublicProperties(Type type) 
    { 
     var matchingProperties = type.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance) 
            .Where(propInfo => propInfo.GetCustomAttributes(typeof(ColumnAttribute), true).Length > 0) 
            .ToArray(); 
     return matchingProperties.Length == 0 ? null : matchingProperties; 
    } 
} 
+2

Da dove viene questo attributo "Colonna"? È un attributo personalizzato che hai creato o è qualcosa proveniente da EF? – Gimly

+0

È un attributo standard utilizzato da EF, ma non nella lib di EF: System.ComponentModel.DataAnnotations.Schema.ColumnAttribute, che si trova in System.ComponentModel.DataAnnotations.dll. – crimbo

+3

Vorrei poterti dare circa 10 upvotes. Mi ha risparmiato un po 'di tempo –

3

Un'altra soluzione alternativa potrebbe essere quella di impostare il campo come interno:

[NotMapped] 
    public dynamic FacebookMetadata { 
     get 
     { 
      return JObject.Parse(this.FacebookMetadataDb); 
     } 
     set 
     { 
      this.FacebookMetadataDb = JsonConvert.SerializeObject(value); 
     } 
    } 

    ///this one 
    internal string FacebookMetadataDb { get; set; } 

e aggiungerlo al modello di visita:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.ManyToManyCascadeDeleteConvention>(); 

     ///here 
     modelBuilder.Entity<FacebookPage>().Property(p => p.FacebookMetadataDb); 

     base.OnModelCreating(modelBuilder); 
    } 
+0

A cosa serve: 'modelBuilder.Conventions.Remove (); '? – urig

+1

Questo è un esempio, la linea pertinente è // qui. –

0

risposta estensione @ di crimbo sopra (https://stackoverflow.com/a/21686896/3264286), ecco il mio cambiamento di includere le proprietà pubbliche con getter privati:

private IEnumerable<PropertyInfo> NonPublicProperties(Type type) 
{ 
    var matchingProperties = type.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Instance) 
           .Where(propInfo => propInfo.GetCustomAttributes(typeof(ColumnAttribute), true).Length > 0) 
           .Union(
             type.GetProperties(BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance) 
              .Where(propInfo => propInfo.GetCustomAttributes(typeof(ColumnAttribute), true).Length > 0 
                   && propInfo.GetGetMethod().IsNull()) 
           ) 
           .ToArray(); 
    return matchingProperties.Length == 0 ? null : matchingProperties; 
} 
0

Un altro modo per gestire questo è quello di definire una configurazione di entità personalizzata e aggiungere un legame per quello.

Nella classe aggiungere una classe che eredita da EntityTypeConfiguration (Questo può essere trovato in System.Data.Entity.ModelConfiguration)

public partial class Report : Entity<int> 
    { 
     //Has to be a property 
     private string _Tags {get; set;} 

     [NotMapped] 
     public string[] Tags 
     { 
      get => _Tags == null ? null : JsonConvert.DeserializeObject<string[]>(_Tags); 
      set => _Tags = JsonConvert.SerializeObject(value); 
     } 

     [MaxLength(100)] 
     public string Name { get; set; } 

     [MaxLength(250)] 
     public string Summary { get; set; } 

     public string JsonData { get; set; } 

     public class ReportConfiguration: EntityTypeConfiguration<Report> 
     { 
      public ReportConfiguration() 
      { 
       Property(p => p._tags).HasColumnName("Tags"); 
      } 
     } 
    } 

Nel suo contesto, aggiungere il seguente:

using Models.ReportBuilder; 
public partial class ReportBuilderContext:DbContext 
{ 
    public DbSet<Report> Reports { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new Report.ReportConfiguration()); 
     base.OnModelCreating(modelBuilder); 
    } 
} 

dei desideri Potrei dire che l'ho trovato da solo, ma sono incappato qui: https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/

Problemi correlati