2011-10-01 122 views
18

我正在使用EF 4.1,并且正在为缺乏枚举支持寻找一个很好的解决方法。 int的支持属性看起来合乎逻辑。首先映射私有财产实体框架代码

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

    private int TypeId { get; set; } 

但是,我怎样才能使这个属性私人,仍然映射它。换句话说:

如何首先使用EF 4.1代码映射私有财产?

+0

我可能会补充一点,EF支持私人setter,所以至少可以防止设置Typ来自课外。 –

回答

10

您无法先在EF代码中映射私有属性。您可以尝试将其更改为protected并将其配置为继承自EntityConfiguration的类。
编辑
现在改变了,看到这个https://stackoverflow.com/a/13810766/861716

+16

他们是一个changin的时代 - 现在是可能的,请参阅http://stackoverflow.com/a/13810766/861716 –

+0

除了@格特的评论,我在EF5中经验地注意到,具有私人设置者的公共属性正确映射使用默认的代码第一个约定。 –

64

这里是您可以在EF使用6+映射选择非公开性质的约定(只需添加[Column]属性的属性)。

在你的情况,你会改变TYPEID到:

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

在你DbContext.OnModelCreating,你需要注册约定:

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

最后,这里的约定:

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

这个“Column”属性来自哪里?它是您创建的自定义属性,还是来自EF的东西? – Gimly

+0

这是由EF使用的标准属性,但不是在EF LIB:System.ComponentModel.DataAnnotations.Schema.ColumnAttribute,这是在System.ComponentModel.DataAnnotations.dll。 – crimbo

+3

希望我可以给你10个upvotes。为我节省了一堆时间 –

3

另一个解决方法可能是将您的字段设置为内部:

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

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

,并把它添加到旅游模式:

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

这是什么好为:'modelBuilder.Conventions.Remove (); '? – urig

+1

这是一个例子,相关行//在这里。 –

0

扩展@ crimbo的回答以上(https://stackoverflow.com/a/21686896/3264286),这里是我的变化,包括与私人干将公共属性:

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

另一种方式处理这个是定义一个自定义的实体配置并为其添加一个绑定。

在你的类添加从EntityTypeConfiguration继承(这可以在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"); 
      } 
     } 
    } 

在您的上下文类添加以下内容:

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

愿望我可以说我自己找到了这个,但是我偶然发现它:https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/

相关问题