【问题标题】:Is it possible to directly reference a many-to-many table using entity framework, code first是否可以使用实体框架直接引用多对多表,代码优先
【发布时间】:2012-03-21 18:03:16
【问题描述】:

我正在使用实体框架并为多对多关系建模。

我已经使用 fluent API 创建了两个实体之间的关系(比如说用户和组):

this.HasMany(t => t.Users)
.WithMany(t => t.Groups)
.Map(
m =>
{
  m.ToTable("GroupMembers");
  m.MapLeftKey("Group_Id");
  m.MapRightKey("User_Id");
});

这很好用,但我也希望能够直接引用 GroupMembers 表。为此,我有类似的东西:

[Table("GroupMembers")]
public class GroupMember
{
    #region Properties

    /// <summary>
    /// Gets or sets the group.
    /// </summary>
    public virtual Group Group { get; set; }

    /// <summary>
    /// Gets or sets the Id of rht group.
    /// </summary>
    [Key]
    [Column("Group_Id", Order = 1)]
    public int GroupId { get; set; }

    /// <summary>
    /// Gets or sets the user.
    /// </summary>
    public virtual User User { get; set; }

    /// <summary>
    /// Gets or sets the Id of the user.
    /// </summary>
    [Key]
    [Column("User_Id", Order = 2)]
    public int UserId { get; set; }

    #endregion
}    

但是,在初始化 DbContext 的过程中会出现以下错误:

指定的架构无效。错误:(381,6):错误 0019: 具有模式 'dbo' 和表 'GroupMembers' 的 EntitySet 'GroupUser' 是 已经定义了。每个 EntitySet 必须引用一个唯一的模式,并且 表。

我相信这是因为实体框架没有意识到 fluent API 中指定的 GroupMembers 表和 GroupMembers 实体表实际上是一回事。换句话说,如果我删除描述多对多关系的 fluent API 代码,那么我就能够成功地初始化 DbContext。

我可以有一个我也可以直接引用的多对多表吗?

【问题讨论】:

    标签: entity-framework-4.1 ef-code-first many-to-many


    【解决方案1】:

    不,你不能。如果您想通过单独的实体访问连接表,您必须用两个一对多关系替换您的多对多关系,并将UserGroup 中的导航属性更改为引用@987654323 @:

    public class Group
    {
        public int GroupId { get; set; }
        public virtual ICollection<GroupMember> Members { get; set; }
    }
    
    public class User
    {
        public int UserId { get; set; }
        public virtual ICollection<GroupMember> Members { get; set; }
    }
    
    modelBuilder.Entity<Group>()
        .HasMany(g => g.Members)
        .WithRequired(gm => gm.Group);
    
    modelBuilder.Entity<User>()
        .HasMany(u => u.Members)
        .WithRequired(gm => gm.User);
    

    你为什么想要这个GroupMember 实体?它不包含任何商业意义,只有引用和键。通常,您可以通过编写 LINQ 查询并使用 GroupUser DbSets/entities 及其导航属性来获取和修改连接表的任何内容。

    【讨论】:

    • 谢谢。用户和组都从基表 Principal 继承,还有另一个表 Permissions,其中包含用户和组的权限。 LINQ 查询类似于: from p in context.Permissions join m in context.GroupMembers on p.PrincipalId 等于 m.GroupId where m.UserId.Equals(principalId) select p 我不太确定如何执行该查询无需直接引用 GroupMembers 表。
    • @Eric:我建议为此创建一个单独的问题,并提供有关模型的更多详细信息。
    • @Eric 我也有同样的问题,fluent api 只能创建实体而不是使用已经存在的实体似乎不合逻辑
    • “不,你不能”,天哪,我希望我能在 9 小时前找到这个答案。
    • 是的,你可以!您只需要将冲突的映射放在不同的上下文中。请参阅下面的答案。
    【解决方案2】:

    我们通过创建一个仅用于定义关系的视图来解决这个问题。我们需要访问查找表中的其他字段。

    视图只是从查找表中选择连接字段。

    【讨论】:

      【解决方案3】:

      是的,您可以...如果您使用另一个上下文

      如果您尝试将多个实体映射到同一个上下文中的同一张表,那么您将收到错误消息。但是如果你把这两个映射放在不同的上下文中,那么就不会有问题了。这样,您可以拥有一个描述与联接表的多对多关系透明的映射,就好像其中只有外键一样......并且您可以拥有另一个具有自己的上下文的映射,以公开实际的联接表,如果您想了解关系的任何属性。

      【讨论】:

      • 这个上下文是否需要配置并维护它自己的迁移集?
      【解决方案4】:

      是的,你可以!检查this。另外,删除 GroupMembers 实体和 IDbSet 集合。

      【讨论】:

      • 这并没有回答问题,恰恰相反。这是关于如何使其自动没有访问表,问题是关于如何访问表。
      • 是的,他试图同时有一个多对多连接(带有隐藏的自动生成的映射表)和两个一对多关系到一个显式映射表。我已经为两者设置了正确的配置,并且它们在独立配置时工作,但是当同时配置时,它会给出原始帖子中提到的错误:“每个 EntitySet 必须引用一个唯一的模式和表。”它们只是两种不兼容的方法。这是有道理的,因为如果 EF 试图自动管理一个连接表,那么维护显式连接表所需的工作就没有意义。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-01
      • 2012-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      相关资源
      最近更新 更多