web-dev-qa-db-ja.com

最初にプライベートプロパティエンティティフレームワークコードをマッピングする

私はEF 4.1を使用しており、列挙型のサポートが不足しているため、適切な回避策を探していました。 intのバッキングプロパティは論理的です。

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

    private int TypeId { get; set; }

しかし、どうすればこのプロパティをプライベートにしてもマッピングできますか?言い換えると:

最初にEF 4.1コードを使用してプライベートプロパティをマップするにはどうすればよいですか?

22
Gluip

最初にEFコードでプライベートプロパティをマップすることはできません。 protectedに変更して、EntityConfigurationから継承したクラスで構成してみてください。
編集
変更されました、これを参照してください https://stackoverflow.com/a/13810766/861716

15

選択した非パブリックプロパティをマップするために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;
    }
}
74
crimbo

別の回避策は、フィールドを内部として設定することです。

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

モデルに見られるように、プロパティへの読み取りアクセスを許可します。したがって、プライベートセッターを使用してセットアクセスをブロックし、EFにマップする必要がある場合があります。このような。

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

これを処理する別の方法は、カスタムエンティティ構成を定義し、そのためのバインディングを追加することです。

クラスに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/

0
rahicks

上記の@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
Delorian