#c_sharp #net #aspnet #aspnet_mvc #entity_framework
В приложении должно присутствовать несколько типов учётных записей пользователей и у каждой должен быть свой набор полей. Одним из вариантов я вижу создание иерархии наследования: public class ApplicationUser : IdentityUser { public string Name { get; set; } public string Surname { get; set; } public IImage AvatarImage { get; set; } public bool IsBlocked { get; set; } public School School { get; set; } public async TaskGenerateUserIdentityAsync(UserManager manager) { var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); return userIdentity; } } public class StudentUser : ApplicationUser { public TeachingType TeachingType { get; set; } public int Grade { get; set; } } public class TeacherUser : ApplicationUser { public bool IsConfirmed { get; set; } public List Subjects { get; set; } } Контекст я вижу таким: public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { } public DbSet TeacherUsers { get; set; } public DbSet StudentUsers { get; set; } } Есть ли способ научить Identity работать с этой иерархией и возвращать сущность пользователя нужного мне типа?
Ответы
Ответ 1
Identity в вашем случае использует самый обычный Entity Framework для хранения учетных записей пользователей - а Entity Framework всегда имел такую возможность. Только контекст вы привели неправильный. Независимо от способа хранения, DbSet должен быть один на иерархию и в нем должен храниться базовый класс. А способов хранения - три: Table per Hierarchy (TPH) - все свалено в одну таблицу. Table per Type (TPT) - на каждый класс по таблице, их первичные ключи объединены отношениями вида 1 - (0..1). Table per Concrete class (TPC) - по таблице на каждый неабстрактный класс. Но DbSet при этом все равно один! Для создания БД первого типа просто добавьте DbSet с базовым типом в контекст - все потомки будут свалены в ту же таблицу автоматически. Если вам больше нравится второй тип - добавьте потомкам атрибут Table. Или перегрузите метод OnModelCreating, указав там примерно следующее: modelBuilder.Entity().ToTable("TeacherUsers"); modelBuilder.Entity ().ToTable("StudentUsers"); Ну а если больше всего нравится третий тип - используйте вот такую конструкцию в том же методе: modelBuilder.Entity ().Map(m => { m.MapInheritedProperties(); m.ToTable("TeacherUsers"); }); modelBuilder.Entity ().Map(m => { m.MapInheritedProperties(); m.ToTable("StudentUsers"); }); Ответ 2
Identity научить можно, но вот возвращаться вам всегда будет IUser. Я бы рекомендовал отказаться от наследования и использовать композицию. Также, на мой взгляд, не нужно мешать identity и ваш domen. Так у вас будет: public class ApplicationUser : IUser { public async TaskGenerateUserIdentityAsync(UserManager manager) { var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); return userIdentity; } public string Id { get; private set; } public string UserName { get; set; } } public class SchoolUser { public virtual ApplicationUser ApplicationUser { get; set; } public string ApplicationUserId { get; set; } public string Name { get; set; } public string Surname { get; set; } public IImage AvatarImage { get; set; } public bool IsBlocked { get; set; } public School School { get; set; } } public class StudentUser : SchoolUser { public TeachingType TeachingType { get; set; } public int Grade { get; set; } } public class TeacherUser : SchoolUser { public bool IsConfirmed { get; set; } public List Subjects { get; set; } } Кроме того, лучше всего будет написать свой "Identity" слой. Как это сделать, можете посмотреть здесь http://weblogs.asp.net/imranbaloch/a-simple-implementation-of-microsoft-aspnet-identity
Комментариев нет:
Отправить комментарий