25 Stimmen

Mapping von privaten Eigenschaften mit Entity Framework Code First

Ich verwende EF 4.1 und war auf der Suche nach einem guten Workaround für das Fehlen von enum-Unterstützung. Eine Backup-Eigenschaft von int scheint logisch.

    [Erforderlich]
    public VenueType Typ
    {
        get { return (VenueType) TypId; }
        set { TypId = (int) value; }
    }

    private int TypId { get; set; }

Aber wie kann ich diese Eigenschaft privat machen und trotzdem mappen. Mit anderen Worten:

Wie kann ich eine private Eigenschaft mit EF 4.1 Code First mappen?

77voto

crimbo Punkte 9192

Hier ist eine Konvention, die Sie in EF 6+ verwenden können, um ausgewählte nicht öffentliche Eigenschaften zuzuordnen (fügen Sie einfach das [Column] Attribut zu einer Eigenschaft hinzu).

In Ihrem Fall würden Sie TypeId wie folgt ändern:

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

In Ihrem DbContext.OnModelCreating müssen Sie die Konvention registrieren:

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

Zuletzt, hier ist die Konvention:

/// 
/// Konvention zur Unterstützung der Zuordnung von privaten oder geschützten Eigenschaften zu EF-Spalten.
/// 
public sealed class NonPublicColumnAttributeConvention : Convention
{

    public NonPublicColumnAttributeConvention()
    {
        Types().Having(NonPublicProperties)
               .Configure((config, properties) =>
                          {
                              foreach (PropertyInfo prop in properties)
                              {
                                  config.Property(prop);
                              }
                          });
    }

    private IEnumerable 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;
    }
}

17voto

Jayantha Lal Sirisena Punkte 20916

Sie können in EF Code First keine privaten Eigenschaften mappen. Sie können es versuchen, indem Sie es in protected ändern und es in einer Klasse konfigurieren, die von EntityConfiguration geerbt ist.
Bearbeiten
Jetzt wurde es geändert, siehe hier https://stackoverflow.com/a/13810766/861716

4voto

Jean F. Punkte 1735

Ein weiterer Workaround könnte sein, Ihr Feld als intern zu setzen:

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

    ///dieses hier
    internal string FacebookMetadataDb { get; set; }

und fügen Sie es Ihrem Modell hinzu:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove();

        ///hier
        modelBuilder.Entity().Property(p => p.FacebookMetadataDb);

        base.OnModelCreating(modelBuilder);
    }

1voto

CatCode91 Punkte 31

Versuchen Sie dieses.

public class UserAccount
{ 
   private string Username { get; set;}
}

public class UserAccountConfiguration :IEntityTypeConfiguration
{
   public void Configure(EntityTypeBuilder builder)
   {
       builder.Property(c => c.Username);
   }
}

und dann in DbContext

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new UserAccount.UserAccountConfiguration());
}

1voto

Prince Owen Punkte 526

Wenn Sie Attributes mögen (genau wie ich) und EF Core verwenden, könnten Sie folgenden Ansatz verwenden.

Zuerst erstellen Sie ein Attribut, um private Eigenschaften zu kennzeichnen:

using System;
using System.ComponentModel.DataAnnotations.Schema;
...

[System.AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public sealed class ShadowColumnAttribute : ColumnAttribute
{
    public ShadowColumnAttribute() { }
    public ShadowColumnAttribute(string name): base(name) { }
}

public static class ShadowColumnExtensions
{
    public static void RegisterShadowColumns(this ModelBuilder builder)
    {
        foreach (var entity in builder.Model.GetEntityTypes())
        {
            var properties = entity.ClrType
                .GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)
                .Select(x => new { prop = x, attr = x.GetCustomAttribute() })
                .Where(x => x.attr != null);

            foreach (var property in properties)
                entity.AddProperty(property.prop);
        }
    }
}

Dann markieren Sie die Eigenschaften, die privat bleiben sollen.

public class MyEntity
{
    [Key]
    public string Id { get; set; }

    public bool SomeFlag { get; set; }

    public string Name => SomeFlag ? _Name : "SomeOtherName";

    [ShadowColumn(nameof(Name))]
    string _Name { get; set; }
}

Zum Schluss fügen Sie dies am Ende Ihrer OnModelCreating-Methode in Ihrem DbContext ein:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    // ...
    builder.RegisterShadowColumns();   
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X