EF Code First:多对多和一对多

时间:2011-06-03 14:45:34

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

这可能只是因为我对EF Code First流利API的了解不足,但我很难过。

我想模拟以下内容:

  • 包含ID和姓名的群组集合
  • 包含ID和姓名的用户集合
  • 每个用户只分配一个主要群组
  • 每个用户可能有零个或多个辅助组

我想要的表结构如下:

  • 编号
  • 名称

用户

  • 编号
  • 名称
  • PrimaryGroupId

SecondaryGroupAssignments

  • 用户ID
  • 的GroupId

我一直在试图用EF Code First模拟这个问题,但我无法接受用户和组之间的关系。很抱歉没有发布任何.NET代码(我很高兴),但无论如何它可能都是错误的。

有没有办法制作EF模型呢?我假设我必须使用Fluent API进行某种配置。也许更好的问题是:Fluent API是否有任何好的,明确的参考资料?

谢谢!

2 个答案:

答案 0 :(得分:16)

试试这个(未经测试):

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

答案 1 :(得分:3)

基于Ladislav的优秀答案,这里是如何在不使用任何映射的情况下完成的 - 只是应用于Model类本身的属性:

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 ICollectionGroup。这allows lazy-loading。性能方面,我不推荐它,但它是可能的。

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

我建议您不要使用EF类的“User”和“Group”类名。它们会使您以后尝试运行的任何SQL变得复杂,必须键入[User]和[Group]才能访问它们,并且在MVC控制器中使用这些类复杂化,其中您的类User将与{{{}}冲突1}} property Context,可让您访问Asp.Net Identity库。