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