Список связанных AplicationUsers внутри ApplicationUser

У меня сегодня другой вопрос.

Я хочу связать список 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 ответ

Есть несколько способов реализовать это, в зависимости от того, как вы хотите использовать эти отношения. Есть проблемы производительности, связанные с различными реализациями.

Например, если вам нужно быстро выполнять запросы к спискам родителей, братьев и сыновей и вносить небольшие изменения в эти данные, вы можете хранить информацию с избыточностью, поэтому у вас есть таблица сыновей / родителей и таблица братьев с некоторыми EF. отображения для этих отношений. В этих таблицах хранятся только первичные ключи участвующих людей, и каждый раз, когда вы изменяете одно из этих отношений (например, добавляете нового сына), вам приходится обновлять одну и ту же информацию в нескольких таблицах.

Однако, если вам нужно много модифицировать данные, а не столько запрашивать, лучше хранить только таблицу "Родители", и список братьев и сыновей можно вывести из нее, выполнив запросы в коде, но не 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"); });
    }

Миграция включает в себя эти таблицы (я добавил целое число Id свойство для сущности ApplicationsUsers для простоты):

        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 не синхронизирует данные Brothers автоматически с данными родителей / сыновей. Таким образом, вам придется явно добавлять пользователей в список братьев при добавлении их в списки родителей / сыновей. Однако списки "Родители и сыновья" автоматически синхронизируются: если вы добавляете пользователя "А" в список "Родители" пользователя "Б" и сохраняете данные, тогда в списке "Родители" пользователя Б будет находиться пользователь "А". Это связано с тем, что отображения родителей и сыновей используют те же свойства навигации. Это не происходит с собственностью братьев.

Другие вопросы по тегам