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



我有以下实体模型

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

这是纯粹简单的多对多关系User&标签我使用的是数据迁移。当我执行命令"添加迁移"或"更新数据库"时我得到以下错误"类型'Kig.DomainObjects.Entities.User'的属性'Tags'上的InversePropertyAttribute无效。属性'Users'不是相关类型'Kigg.DomainObjects.Entegies.Tag'上的有效导航属性。请确保该属性存在并且是有效的引用或集合导航属性。"

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

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

注意:我不会在这里讨论我的设计。我在问,在标记时是否可以这样做。用户是受保护的还是内部的

我不知道如何使它与数据注释一起工作,但使用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();
}

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

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

看起来,您可以使用这种方法映射非公共导航属性,以生成所需的数据库模式。但是你似乎对它没有任何用处。

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

最新更新