2011-10-01 11 views
18

Estoy usando EF 4.1 y busqué una buena solución para la falta de soporte de enum. Una propiedad de respaldo de int parece lógica.mapeo de código de entidad de entidad de propiedad privada primero

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

    private int TypeId { get; set; } 

Pero, ¿cómo puedo hacer esta propiedad privada y seguir asignándola? En otras palabras:

¿Cómo puedo mapear una propiedad privada usando primero el código EF 4.1?

+0

Podría agregar que EF admite entidades privadas, por lo que al menos puede evitar la configuración. eid desde fuera de tu clase. –

Respuesta

10

primero no se pueden asignar las propiedades privadas en el código EF. Puede intentarlo cambiándolo a protected y configurándolo en una clase heredada de EntityConfiguration.
Editar
Ahora se cambia, Ver este https://stackoverflow.com/a/13810766/861716

+16

Veces están cambiando -es posible ahora, vea http://stackoverflow.com/a/13810766/861716 –

+0

Además de la observación de @Gert, he notado empíricamente en EF5 que las propiedades públicas con instaladores privados mapean correctamente con el código predeterminado primero convenciones. –

64

Aquí hay una convención que puede utilizar en EF 6+ mapear las propiedades no públicos seleccionados (sólo tiene que añadir el atributo [Column] a una propiedad).

En su caso, usted cambia a TypeId:

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

En su DbContext.OnModelCreating, tendrá que registrar la convención:

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

Por último, aquí está la convención:

/// <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

¿De dónde viene este atributo "Columna"? ¿Es un atributo personalizado que ha creado o es algo que proviene de EF? – Gimly

+0

Es un atributo estándar utilizado por EF, pero no en EF lib: System.ComponentModel.DataAnnotations.Schema.ColumnAttribute, que se encuentra en System.ComponentModel.DataAnnotations.dll. – crimbo

+3

Desearía poder darte unos 10 votos favorables. Me salvó un montón de tiempo –

3

Otra solución podría ser establecer su campo como interno:

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

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

y añadirlo al recorrido modelo:

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

Para qué sirve esto: 'modelBuilder.Conventions.Remove (); '? – urig

+1

Este es un ejemplo, la línea relevante es // aquí. –

0

respuesta de Ampliación @ crimbo anterior (https://stackoverflow.com/a/21686896/3264286), aquí está mi cambio para incluir las propiedades públicas con captadores privadas:

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

Otra forma manejar esto es definir una configuración de entidad personalizada y agregar un enlace para eso.

En su clase de agregar una clase que hereda de EntityTypeConfiguration (Esto se puede encontrar en 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"); 
      } 
     } 
    } 

En el contexto añadir los siguientes:

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

Wish Podría decir que encontré esto por mi cuenta, pero me encontré con esto aquí: https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/

Cuestiones relacionadas