ApplicationUser内部相关AplicationUsers的列表

时间:2016-11-02 16:43:52

标签: entity-framework asp.net-mvc-5 ef-code-first entity-relationship ef-fluent-api

我今天有另一个问题。

我想将ApplicationUser列表关联到应用程序用户......

像这样......

public class ApplicationUser : IdentityUser
{
    //Here are the Added Needed Values to IdentityUser to PlenaMenteTrabajando Application.

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ROLES Role { get; set; 

    public virtual ICollection<ApplicationUser> Brothers { get; set; }
    public virtual ICollection<ApplicationUser> Parents{ get; set; }
    public virtual ICollection<ApplicationUser> Sons { get; set; }


    //Other Stuff
}

我不知道如何处理这些关系......

建立另一个存储兄弟,父母和儿子的实体?

像这样......

public class Brother
{
    public int BrotherId{ get; set; }
    public int UserId { get; set; }

    public virtual ApplicationUser User { get; set; }
    public virtual ICollection<ApplicationUser> Brothers{ get; set; }
}

或者我应该使用Fluent API来设置关系吗? (但我不知道怎么做)

或两者兼而有之?

感谢阅读!

1 个答案:

答案 0 :(得分:0)

根据您希望使用此关系的方式,有多种方法可以实现此目的。存在与不同实现相关的性能问题。

例如,如果您必须对Parent,Brothers and Sons列表进行大量快速查询并且很少修改这些数据,您可以冗余地存储信息,因此您有一个Sons / Parents表和Brothers表,与这些关系的一些EF映射。这些表只存储相关人员的主键,每次修改其中一个关系(例如,添加新子)时,您必须在多个表中更新相同的信息。

但是,如果你必须进行大量的数据修改而不是那么多的查询,那么最好只存储Parents表,并且可以通过在那里进行查询来推断Brothers and Sons的列表。代码,但不是EF映射。

冗余表的示例:使用这些映射:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>().HasMany(u => u.Parents).WithMany(u => u.Sons).Map( x => { x.MapRightKey("ParentId"); x.MapLeftKey("SonId"); x.ToTable("ParentsSons"); } );
        modelBuilder.Entity<ApplicationUser>().HasMany(u => u.Sons).WithMany(u => u.Parents);
        modelBuilder.Entity<ApplicationUser>().HasMany(u => u.Brothers).WithMany().Map(x => { x.MapRightKey("BrotherId"); x.MapLeftKey("Id"); x.ToTable("Brothers"); });
    }

迁移包括这些表(为了简单起见,我向ApplicationsUsers实体添加了一个整数Id属性):

        CreateTable(
            "dbo.ApplicationUsers",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    FirstName = c.String(),
                    LastName = c.String(),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.Brothers",
            c => new
                {
                    Id = c.Int(nullable: false),
                    BrotherId = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.Id, t.BrotherId })
            .ForeignKey("dbo.ApplicationUsers", t => t.Id)
            .ForeignKey("dbo.ApplicationUsers", t => t.BrotherId)
            .Index(t => t.Id)
            .Index(t => t.BrotherId);

        CreateTable(
            "dbo.ParentsSons",
            c => new
                {
                    SonId = c.Int(nullable: false),
                    ParentId = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.SonId, t.ParentId })
            .ForeignKey("dbo.ApplicationUsers", t => t.SonId)
            .ForeignKey("dbo.ApplicationUsers", t => t.ParentId)
            .Index(t => t.SonId)
            .Index(t => t.ParentId);

使用这些表稍微玩一下的示例方法。如果通过它进行调试,则可以检查实体并检查“父母和子”列表的内容。 TestContext仅包含一个DbSet用户:public DbSet<ApplicationUser> Users { get; set; }

    public void Test()
    {
        using (var context = new TestContext())
        {
            var arya = new ApplicationUser()
            {
                FirstName = "Arya",
                Parents = new List<ApplicationUser>
                {
                    new ApplicationUser { FirstName = "Eddard" },
                    new ApplicationUser { FirstName = "Catelyn" }
                }
            };
            context.Users.Add(arya);
            context.SaveChanges();

            var eddard = context.Users.First(u => u.FirstName == "Eddard");
            var jon = new ApplicationUser { FirstName = "Jon" };
            eddard.Sons.Add(jon);
            context.SaveChanges();

            var eddardFromContext = context.Users.First(u => u.FirstName == "Eddard");
            var catelynFromContext = context.Users.First(u => u.FirstName == "Catelyn");
        }
    }

我离开了兄弟名单。请注意,EF不会自动将兄弟数据与Parents / Sons数据同步。因此,在将用户添加到“父/子”列表时,您必须明确地将用户添加到“兄弟”列表中。但是,Parent and Sons列表会自动同步:如果您将用户A添加到用户B的Parents列表并保留数据,则用户B的Parents列表将包含用户A.这是因为Parents和Sons的映射使用了相同的导航属性。 Brothers属性不会发生这种情况。