首先映射私有属性实体框架代码

时间:2011-10-01 11:32:36

标签: entity-framework ef-code-first private-members

我正在使用EF 4.1,并且因缺乏枚举支持而寻找一个很好的解决方法。 int的支持属性似乎是合乎逻辑的。

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

    private int TypeId { get; set; }

但是如何将此属性设为私有并仍然映射它。换句话说:

如何首先使用EF 4.1代码映射私有属性?

8 个答案:

答案 0 :(得分:71)

以下是您可以在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;
    }
}

答案 1 :(得分:13)

您无法先在EF代码中映射私有属性。您可以尝试将其更改为protected并在继承自EntityConfiguration的类中对其进行配置。
修改
现在它已更改,请参阅此https://stackoverflow.com/a/13810766/861716

答案 2 :(得分:4)

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

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

答案 3 :(得分:1)

尝试一下。

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



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

,然后在DbContext中

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

答案 4 :(得分: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;
}

答案 5 :(得分: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/

答案 6 :(得分:0)

如您的模型中所示,您授予对该属性的读取权限。因此,您可能希望阻止设置访问并使用私有设置器映射到EF。像这样。

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

答案 7 :(得分:0)

如果您喜欢 const express = require("express"); // eslint-disable-next-line no-unused-vars // const bodyParser = require('body-parser'); const path = require("path"); const app = express(); const port = process.env.PORT || 8080; app.use(express.static(path.join(__dirname, "build"))); // This route serves the React app app.get('/', (req, res) => res.sendFile(path.resolve(__dirname, "build", "index.html"))); app.listen(port, () => console.log(`Server listening on port ${port}`)); (像我一样)并且正在使用 EF Core。您可以使用以下方法。

首先,创建一个属性来标记私有或属性:

Attributes

然后,标记您希望保密的属性。

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 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; } } 中,将其放入您的 DbContext 方法中:

OnModelCreating