【问题标题】:EF Code First: Many-to-many and one-to-manyEF Code First:多对多和一对多
【发布时间】:2011-09-07 21:17:48
【问题描述】:

这可能只是因为我缺乏对 EF Code First fluent API 的了解,但我被难住了。

我想建模以下内容:

  • 带有 ID 和名称的 Groups 集合
  • 具有 ID 和名称的 Users 集合
  • 每个用户都被分配到一个主要组
  • 每个用户可能有零个或多个辅助组

我要使用的表结构如下所示:

群组

  • 身份证
  • 姓名

用户

  • 身份证
  • 姓名
  • PrimaryGroupId

SecondaryGroupAssignments

  • 用户ID
  • GroupId

我一直在努力尝试使用 EF Code First 对此进行建模,但我无法让它同时接受用户和组之间的关系。很抱歉没有发布任何 .NET 代码(我很高兴),但无论如何它可能都是错误的。

有没有办法让 EF 建模这个?我假设我必须使用 Fluent API 进行某种配置。也许更好的问题是:对于 Fluent API 是否有任何好的、明确的参考?

谢谢!

【问题讨论】:

    标签: database entity-framework-4.1 ef-code-first relationships fluent-interface


    【解决方案1】:

    基于 Ladislav 的出色回答,以下是不使用任何映射的方法 - 只是应用于模型类本身的属性:

    public class Group 
    {
        public int Id { get; set; }
    
        [MaxLength(300)]
        public string Name { get; set; }
    
        public ICollection<User> Users { get; set; }
    }
    
    public class User
    {
        public int Id { get; set; }
    
        [MaxLength(300)]
        public string Name { get; set; }
    
        [ForeignKey("PrimaryGroup")]
        public int PrimaryGroupId { get; set; }
        [Required]
        public Group PrimaryGroup { get; set; }
    
        [InverseProperty("Users")]
        public ICollection<Group> SecondaryGroups { get; set; }
    }
    

    注意事项

    如果需要,可以将虚拟关键字添加到 2 个ICollections 和Group。这个allows lazy-loading。性能方面,我不推荐,但有可能。

    我将MaxLength 属性包含在300 的任意(但安全)长度中,因为在没有MaxLength 的情况下将字符串放在EF 中会使NVarChar(MAX) 列的性能降低。与所要求的内容完全无关,但最好发布好的代码。

    我建议不要为您的 EF 类命名“用户”和“组”。它们将使您稍后尝试运行的任何 SQL 复杂化,必须键入 [User] 和 [Group] 才能访问它们,并在 MVC 控制器中使用这些类变得复杂,您的类 User 将与 Context 属性冲突User 让您可以访问 Asp.Net 身份库。

    【讨论】:

      【解决方案2】:

      试试这个(未经测试):

      public class Group 
      {
          public int Id { get; set; }
          public string Name { get; set; }
      
          public virtual ICollection<User> PrimaryUsers { get; set; }
          public virtual ICollection<User> SecondaryUsers { get; set; } 
      }
      
      public class User
      {
          public int Id { get; set; }
          public string Name { get; set; }
          public int PrimaryGroupId { get; set; }
      
          public virtual Group PrimaryGroup { get; set; }
          public virtual ICollection<Group> SecondaryGroups { get; set; }
      }
      
      public class Context : DbContext
      {
          public DbSet<User> Users { get; set; }
          public DbSet<Group> Groups { get; set; }
      
          protected override void OnModelCreating(DbModelBuilder modelBuilder)
          {
              base.OnModelCreating(modelBuilder);
      
              modelBuilder.Entity<User>()
                          .HasRequired(u => u.PrimaryGroup)
                          .WithMany(g => g.PrimaryUsers)
                          .HasForeignKey(u => u.PrimaryGroupId)
                          .WillCascadeOnDelete(false);
      
              modelBuilder.Entity<User>()
                          .HasMany(u => u.SecondaryGroups)
                          .WithMany(g => g.SecondaryUsers)
                          .Map(m => m.MapLeftKey("UserId")
                                     .MapRightKey("GroupId")
                                     .ToTable("SecondaryGroupAssignments"));
          }
      }
      

      【讨论】:

      • 我只能说,Ladislav,这是我有幸遇到/用来解决我的确切问题的最有用的帖子之一!谢谢!
      • Lad 是 Entity Framework 的人,非常感谢有这么好的资源。堆栈很棒的另一个原因!
      猜你喜欢
      • 2013-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多