我可以使用EF6代码优先映射映射受保护的ICollection吗?

时间:2015-05-12 19:51:24

标签: c# entity-framework entity-framework-6

鉴于课程:

public class User
{
    public int Id { get; protected set; }
    protected virtual ICollection<Role> UserRoles { get; set; }

    public IEnumerable<Role> Roles
    {
        get { return new ReadOnlyCollection<Role>(UserRoles.ToArray()); }
    }
}

如何使用EF6代码优先映射映射UserRoles?我不想暴露我的实体之外的任何ICollection功能。我也不想用持久性信息污染我的域模型。我希望它能保持持久性不可知。这意味着属性已经消失。

2 个答案:

答案 0 :(得分:0)

也许this post可以帮助你 - 尽管它是EF 6 alpha,所以我不知道它是否仍适用。

从本质上讲,您可以在OnModelCreating()方法中定义一个自定义约定,该约定包含所有非公共字段并将其包含在您的模型中(直接从链接页面获取代码片段):

public class MyContext : DbContext
{
    // DbSets etc. defined here

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder
        .Entities()
        .Configure(c =>
            {
                var nonPublicProperties = c.ClrType.GetProperties(BindingFlags.NonPublic|BindingFlags.Instance);

                foreach (var p in nonPublicProperties)
                {
                    c.Property(p).HasColumnName(p.Name);
                }
            });
      }
}

答案 1 :(得分:0)

我想出了如何使用反射来做到这一点。以下是它的要点:

internal class UserMapping : EntityTypeConfiguration<User>
{
    public UserMapping()
    {
        ToTable("Users");
        HasKey(u => u.Id);
        Property(u => u.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
            .HasColumnName("UserID");

        var userType = typeof (User);
        var propertyInfo = userType.GetProperty("UserRoles", BindingFlags.NonPublic | BindingFlags.Instance);
        var parameter = Expression.Parameter(typeof (User), "u");
        var property = Expression.Property(parameter, propertyInfo);
        var funcType = typeof (Func<,>).MakeGenericType(userType, typeof (ICollection<Role>));// propertyInfo.PropertyType);
        var lambda = Expression.Lambda(funcType, property, parameter);

        ((ManyNavigationPropertyConfiguration<User, Role>)GetType().GetMethod("HasMany")
            .MakeGenericMethod(typeof(Role))
            .Invoke(this, new object[] { lambda }))
            .WithMany()
            .Map(m =>
            {
                m.MapLeftKey("UserId");
                m.MapRightKey("RoleId");
                m.ToTable("UserRoles");
            });
        }
    }
}

很高兴@darkgray对这个答案很感兴趣:

How to convert PropertyInfo to property expression and use it to invoke generic method?