2011-10-01 92 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/