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

发布于 2024-12-07 16:27:09 字数 332 浏览 1 评论 0原文

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

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

    private int TypeId { get; set; }

但我怎样才能将这个属性设为私有并仍然映射它。换句话说:

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

I am using EF 4.1 and was look for a nice workaround for the lack of enum support. A backing property of int seems logical.

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

    private int TypeId { get; set; }

But how can I make this property private and still map it. In other words:

How can I map a private property using EF 4.1 code first?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

仅一夜美梦 2024-12-14 16:27:09

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

Here's a convention you can use in EF 6+ to map selected non-public properties (just add the [Column] attribute to a property).

In your case, you'd change TypeId to:

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

In your DbContext.OnModelCreating, you'll need to register the convention:

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

Finally, here's the convention:

/// <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;
    }
}
说不完的你爱 2024-12-14 16:27:09

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

you can't map private properties in EF code first. You can try it changing it in to protected and configuring it in a class inherited from EntityConfiguration .
Edit
Now it is changed , See this https://stackoverflow.com/a/13810766/861716

我为君王 2024-12-14 16:27:09

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

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

Another workaround might be to set your field as internal:

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

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

and add it to tour model:

    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);
    }
笑咖 2024-12-14 16:27:09

如果您喜欢 Attributes(像我一样)并且您正在使用 EF Core。您可以使用以下方法。

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

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<ShadowColumnAttribute>() })
                .Where(x => x.attr != null);

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

然后,标记您想要保持私有的属性。

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 方法的末尾:

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

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

If you like Attributes (like me) and you're using EF Core. You could use the following approach.

First, Create an attribute to mark private or properties:

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<ShadowColumnAttribute>() })
                .Where(x => x.attr != null);

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

Then, mark the properties you would like to stay private.

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

Finally, in your DbContext, place this at the end of your OnModelCreating method:

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

    // ...
    builder.RegisterShadowColumns();   
}
情痴 2024-12-14 16:27:09

试试这个。

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

Try this.

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



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

and then in DbContext

protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
    modelBuilder.ApplyConfiguration(new UserAccount.UserAccountConfiguration());
  }
郁金香雨 2024-12-14 16:27:09

扩展@crimbo上面的答案( https://stackoverflow.com/a/21686896/3264286 ),这是我要包括的更改具有私有 getter 的公共属性:

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

Extending @crimbo's answer above ( https://stackoverflow.com/a/21686896/3264286 ), here's my change to include public properties with private getters:

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;
}
忘年祭陌 2024-12-14 16:27:09

处理此问题的另一种方法是定义自定义实体配置并为其添加绑定。

在您的类中添加一个继承自 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);
    }
}

希望我可以说我自己找到了这个,但我在这里偶然发现了它:< a href="https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/" rel="nofollow noreferrer">https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/

Another way to handle this is to defines a custom entity configuration and add a binding for that.

In your class add a class that inherits from EntityTypeConfiguration (This can be found in 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");
            }
        }
    }

In your context add the following:

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

Wish I could say I found this on my own, but I stumbled upon it here:https://romiller.com/2012/10/01/mapping-to-private-properties-with-code-first/

千笙结 2024-12-14 16:27:09

正如您的模型中所见,您授予对该属性的读取访问权限。因此,也许您想阻止集合访问并使用私有 setter 映射到 EF。像这样。

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

As seen in your model you grant read access to the property. So maybe you want to block set access and map to EF using a private setter. Like this.

[Required]
private int TypeId { get; private set; }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文