1

我有以下实体模型

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

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

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

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

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

4

2 回答 2

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。)

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

看起来您可以使用这种方法映射非公共导航属性来生成预期的数据库模式。但似乎你可以用它做任何有用的事情。

于 2012-03-26T16:57:06.823 回答
0

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

于 2012-03-26T12:23:20.117 回答