web-dev-qa-db-fra.com

mappage premier code cadre de l'entité de propriété privée

J'utilise EF 4.1 et cherchais une solution de contournement de Nice pour le manque de support enum Une propriété de support de int semble logique. 

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

    private int TypeId { get; set; }

Mais comment puis-je rendre cette propriété privée et quand même la cartographier? En d'autres termes:

Comment mapper une propriété privée à l'aide du code EF 4.1 en premier?

20
Gluip

vous ne pouvez pas mapper d'abord les propriétés privées dans le code EF. Vous pouvez essayer de le changer en protected et de le configurer dans une classe héritée de EntityConfiguration.
Edit
Maintenant, il est changé, voir ceci https://stackoverflow.com/a/13810766/861716

13

Voici une convention que vous pouvez utiliser dans EF 6+ pour mapper des propriétés non publiques sélectionnées (ajoutez simplement l'attribut [Column] à une propriété).

Dans votre cas, vous modifieriez TypeId en:

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

Dans votre DbContext.OnModelCreating, vous devrez enregistrer la convention:

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

Enfin, voici la convention:

/// <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;
    }
}
70
crimbo

Une autre solution consiste à définir votre champ comme étant interne:

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

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

et l'ajouter au modèle de tour:

    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);
    }
4
Jean F.

Comme vous le voyez dans votre modèle, vous accordez un accès en lecture à la propriété. Alors peut-être que vous voulez bloquer l’accès aux ensembles et mapper vers EF en utilisant un passeur privé. Comme ça.

[Required]
private int TypeId { get; private set; }
0
Jonathan Ramos

Une autre façon de gérer cela consiste à définir une configuration d'entité personnalisée et à ajouter une liaison pour cela. 

Dans votre classe, ajoutez une classe qui hérite de EntityTypeConfiguration (vous pouvez la trouver dans 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");
            }
        }
    }

Dans votre contexte, ajoutez ce qui suit:

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

J'aimerais pouvoir dire que j'ai trouvé cela par moi-même, mais je suis tombé dessus ici: https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/

0
rahicks

En prolongeant la réponse de @ crimbo ci-dessus ( https://stackoverflow.com/a/21686896/3264286 ), voici ma modification pour inclure les propriétés publiques avec des getters privés:

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
Delorian