当属性受到保护或内部时,具有数据库迁移的InverseProperty不起作用

时间:2012-03-26 12:11:53

标签: entity-framework orm entity-framework-4.3 entity-framework-5

我有以下实体模型

public class User
{
        public virtual long Id{get; set;}
        [InverseProperty("Users")]
        public virtual ICollection<Tag> Tags { get; protected set; } 
}

public class Tag
{
        public virtual long Id{get; set;}
        internal protected virtual ICollection<User> Users { get;  set; }
}

这是纯粹简单的多对多关系用户&amp;标签 我正在使用数据迁移。当我执行Add-Migration或Update-Database命令时 我收到以下错误“类型'Kigg.DomainObjects.Entities.User'上的属性'标签'上的InversePropertyAttribute无效。属性'Users'不是相关类型'Kigg.DomainObjects.Entities上的有效导航属性。标记'。确保该属性存在并且是有效的引用或集合导航属性。“

当我将Tag中的Users属性的访问修饰符更改为public时,它运行正常,而且生成就是我想要的。

从我的设计角度来看,我想隐藏Tag.Users属性并使其受保护或内部保留以供内部使用,因为我不想将其暴露给公共API。

注意:我不是在这里讨论我的设计。我问在Tag.Users受保护或内部时是否可以这样做?

2 个答案:

答案 0 :(得分:2)

我不知道如何使用数据注释,但使用Fluent API,您可以应用并尝试这里的技巧:http://blog.cincura.net/232731-mapping-private-protected-properties-in-entity-framework-4-x-code-first/

对于您的模型,它将如下所示:

public class User
{
    public virtual long Id{get; set;}
    public virtual ICollection<Tag> Tags { get; protected set; } 
}

public class Tag
{
    public virtual long Id{get; set;}
    internal protected virtual ICollection<User> Users { get;  set; }

    public class PropertyAccessors
    {
        public static readonly Expression<Func<Tag, ICollection<User>>> Users
            = t => t.Users;
    }
}

FluentAPI中的映射:

modelBuilder.Entity<User>()
    .HasMany(u => u.Tags)
    .WithMany(Tag.PropertyAccessors.Users);

这有效并创造了预期的多对多关系。

但我不确定你是否可以对该导航属性做任何有用的事情。你拥有属性protectedvirtual这一事实让我猜你基本上想要在实体类或派生类中使用延迟加载支持。

问题在于,显然(根据我的测试至少)延迟加载不适用于除public属性之外的任何其他内容。加载的标记是代理,但导航集合始终为null(除非属性为public)。

此外,即使是热切而明确的加载也不起作用:

Tag课程之外:

// Eager loading
var tag = context.Tags.Include(Tag.PropertyAccessors.Users).First();

// Explicit loading
var tag2 = context.Tags.First();
context.Entry(tag2).Collection(Tag.PropertyAccessors.Users).Load();

Tag类内部(Tag中的一些获取上下文的方法):

public DoSomething(MyContext context)
{ 
    // Eager loading
    var tag = context.Tags.Include(t => t.Users).First();

    // Explicit loading
    context.Entry(this).Collection(t => t.Users).Load();
}

在所有情况下,我都会得到一个异常,即实体Users上的属性Tag不是有效的导航属性。 (只要我创建属性public,该异常就会消失。)

我不知道添加/删除/更新关系是否有效。 (我怀疑。)

看起来您可以使用此方法映射非公共导航属性以生成预期的数据库架构。但似乎你无能为力。

答案 1 :(得分:0)

我对EF5了解不多,但您可以使用属性InternalsVisibleToAttribute使内部成员对特定程序集可见。