mapping private property entity framework code first

前端 未结 7 1771
遇见更好的自我
遇见更好的自我 2020-11-27 17:23

I am using EF 4.1 and was look for a nice workaround for the lack of enum support. A backing property of int seems logical.

    [Required]
    public VenueT         


        
相关标签:
7条回答
  • 2020-11-27 17:28

    Here's a convention you can use in EF 6+ to map selected non-public properties (just add the [Column] attribute to a property).

    In your case, you'd change TypeId to:

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

    In your DbContext.OnModelCreating, you'll need to register the convention:

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

    Finally, here's the 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;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 17:34

    Another way to handle this is to defines a custom entity configuration and add a binding for that.

    In your class add a class that inherits from EntityTypeConfiguration (This can be found 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");
                }
            }
        }
    

    In your context add the following:

    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 I could say I found this on my own, but I stumbled upon it here:https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/

    0 讨论(0)
  • 2020-11-27 17:38

    Try this.

      public class UserAccount
        { 
           private string Username { get; set;}
        }
    
    
    
       public class UserAccountConfiguration :IEntityTypeConfiguration<UserAccount>
         {
           public void Configure(EntityTypeBuilder<UserAccount> builder)
             {
               builder.Property(c => c.Username);
             }
    }
    

    and then in DbContext

    protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
        modelBuilder.ApplyConfiguration(new UserAccount.UserAccountConfiguration());
      }
    
    0 讨论(0)
  • 2020-11-27 17:46

    As seen in your model you grant read access to the property. So maybe you want to block set access and map to EF using a private setter. Like this.

    [Required]
    private int TypeId { get; private set; }
    
    0 讨论(0)
  • 2020-11-27 17:48

    Extending @crimbo's answer above ( https://stackoverflow.com/a/21686896/3264286 ), here's my change to include public properties with private getters:

    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 讨论(0)
  • 2020-11-27 17:53

    you can't map private properties in EF code first. You can try it changing it in to protected and configuring it in a class inherited from EntityConfiguration .
    Edit
    Now it is changed , See this https://stackoverflow.com/a/13810766/861716

    0 讨论(0)
提交回复
热议问题