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