Хобрук: Ваш путь к мастерству в программировании

Настройка SimpleMembership с моей собственной базой данных в MVC 4/EF

Я работаю над проектом с использованием ASP.Net MVC4, где я использую SimpleMembership для работы с системой членства.

В дополнение к таблице UserProfile, где я должен хранить данные по умолчанию, у меня есть две таблицы в моей собственной базе данных (Student, Teacher).

Я настроил регистрацию, добавив новое поле, где я прошу нового пользователя определить, является ли он учителем или учеником.

public class UsersContext : DbContext
{
    //public UsersContext()
    //    : base("DefaultConnection")
    //{
    //}
    public DbSet<Student> Students { get; set; }
    public DbSet<Teacher> Teachers { get; set; }
    public DbSet<UserProfile> UserProfiles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserProfile>()
            .HasRequired(u => u.Student)
            .WithOptional(p => p.UserProfile)
            .Map(m => m.MapKey("IDStudent"));

        modelBuilder.Entity<UserProfile>()
            .HasRequired(u => u.Teacher)
            .WithOptional(p => p.UserProfile)
            .Map(m => m.MapKey("IDTeacher"));
    }
}

И таблица профиля пользователя становится такой

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string AccountType { get; set; }
    public virtual Student student { get; set; }
    public virtual Teacher teacher { get; set; }
}

Я добавил этот внешний ключ в оба класса Student , Teacher

public virtual UserProfile UserProfile { get; set; }

Контроллер учетной записи / Класс регистрации

WebSecurity.CreateUserAndAccount(
    model.UserName,
    model.Password,
    new { AccountType = model.AccountType },
    false);

WebSecurity.Login(model.UserName, model.Password);
UsersContext db = new UsersContext();

var membership = (SimpleMembershipProvider)Membership.Provider;
membership.ValidateUser(model.UserName, model.Password);
membership.ConfirmAccount(model.UserName, model.Password);
UserProfile user = db.UserProfiles.FirstOrDefault(u => u.UserName.ToLower() == model.UserName.ToLower());

if (model.AccountType == "Teacher")
{
    if (userid != null) 
        CreateNewTeacher(user.UserId , model.UserName);
}

if (model.AccountType == "Student")
{
    if (userid != null) 
        CreateNewStudentt(user.UserId , model.UserName);
}

После написания этих двух классов

public void CreateNewStudent( int id, string username)
{
    // Attempt to register the user
    using (UsersContext db = new UsersContext())
    {
        Student student = new Student {User_Name = username};
        student.id=id;
        db.Students.Add(student);
        db.SaveChanges();
    }
}

public void CreateNewTeacher(int id,string username)
{
    using (UsersContext db = new UsersContext())
    {    
        Teacher teacher = new Teacher();
        teacher.id=id;
        db.Teacher.Add(teacher);
        db.SaveChanges();
    }
}

Мой вопрос: на каком уровне я должен создать пользователя в своей собственной таблице (я хотел бы сохранить тот же идентификатор). Итак, я хотел бы знать, когда простое членство создает пользователя в своих таблицах, чтобы скопировать его в мою.

Как я могу получить идентификатор пользователя!

Хороша ли моя стратегия работы с бухгалтерией! или я ошибаюсь, думая таким образом.

ОБНОВЛЕНИЕ Я добавил [ключ] (он не был сгенерирован)

 public partial class Agent
    {
        public Teacher()
        {
            this.Tasks = new HashSet<Tasks>();
        }

         [Key]
        public int ID_Teacher { get; set; }
        public string Name_Teacher { get; set; }
        public System.DateTime Bday_Teacher { get; set; }
        public string User_Name { get; set; }

        public virtual ICollection<Task> Tasks { get; set; }


    }


  public partial class Task
    {
         [Key, ForeignKey("Teacher"), Column(Order = 0)]
        public int ID_Teacher { get; set; }

         [Key, ForeignKey("Student"), Column(Order = 1)]
        public int ID_Student { get; set; }

         [Key, ForeignKey("DateT"), Column(Order = 2)]
        public int ID_DateT { get; set; }

         [Key]
        public Nullable<int> ID_Comment { get; set; }

        public virtual Teacher Teacher { get; set; }
        public virtual Student Student { get; set; }
        public virtual DateT DateT { get; set; }
    }

Я ценю ваше время и усилия!

С уважением ,


  • Похоже, вы уже нашли идентификатор пользователя. Это больше похоже на вопрос для Code Review. 03.04.2013
  • Я ценю вашу помощь, у меня возникает проблема всякий раз, когда я сохраняю (Учитель/Клиент) EntityType «Учитель» не имеет определенного ключа. Определите ключ для этого EntityType. . зная, что я создаю свою собственную базу данных из базы данных SQL Server. Какие-либо предложения ! 03.04.2013
  • Можете ли вы опубликовать свой Teacher класс? 03.04.2013
  • Вам нужно создать отношение one-to-one между UserProfile and Student, а также между UserProfile and Teacher. Я обычно использую Property Mapping, а не fluent api 03.04.2013
  • @Trickery: я только что поделился кодом, который вы просили! 03.04.2013

Ответы:


1

Вам нужно создать отношение one-to-one между UserProfile and Student, а также между UserProfile and Teacher. Я обычно использую Property Mapping, а не fluent api

Попробуйте это для сущностей, я пошел дальше и создал для вас связь между Teacher and Student:

[Table("UserProfile")]
public class UserProfile
{
  [Key]
  [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
  public int UserId { get; set; }
  public string UserName { get; set; }
  public string AccountType { get; set; }   
}


public class Teacher
{
   [Key]
   [ForeignKey("UserProfile")]
   [DatabaseGeneratedAttribute(DatabaseGeneratedOption.none)]
   public int UserId { get; set; }

   public string Name { get; set; }

   public virtual ICollection<Student> Student{ get; set; }
   public virtual UserProfile UserProfile { get; set; }
}

public class Student
{
   [Key]
   [ForeignKey("UserProfile")]
   [DatabaseGeneratedAttribute(DatabaseGeneratedOption.none)]
   public int UserId { get; set; }

   [ForeignKey("Teacher")]       
   public int? TeacherId{ get; set; }

   public string Name { get; set; }

   public virtual UserProfile UserProfile{ get; set; }
   public virtual Teacher teacher { get; set; }
}

В вашем Контроллере учетных записей попробуйте следующее:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model)
    {
        if (ModelState.IsValid)
        {
            // Attempt to register the user
            try
            {
                WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { AccountType = model.AccountType }, false);
                WebSecurity.Login(model.UserName, model.Password);

                var userProfile = db.UserProfiles.Local.SingleOrDefault(u => u.UserName == User.Identity.Name)
                                ?? db.UserProfiles.SingleOrDefault(u => u.UserName == User.Identity.Name);

                if (userProfile.AccountType.ToLower() == "teacher")
                {
                    return RedirectToAction("Create", "Teacher"); //Created a Teacher Controller separate
                }

                return RedirectToAction("Create", "Student"); //same with Student
            }
            catch (MembershipCreateUserException e)
            {
                ModelState.AddModelError("", ErrorCodeToString(e.StatusCode));
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

Ваши Student или Teacher действия по созданию должны выглядеть так внутри контроллеров ученика или учителя:

//
    // GET: /Student/
    [HttpGet]
    public ActionResult Create()
    {            
        return View();
    }

    //
    // POST: /Student/
    [HttpPost]
    public ActionResult Create(StudentViewModel model)
    {
        if (ModelState.IsValid)
        {
            using (UsersContext db = new UsersContext())
            {
                var userProfile = db.UserProfiles.Local.SingleOrDefault(u => u.UserName == User.Identity.Name)
                                ?? db.UserProfiles.SingleOrDefault(u => u.UserName == User.Identity.Name);
                if (userProfile != null)
                {
                    var student= new Student
                                     {
                                         UserProfile = userProfile,
                                         Name= model.Name                                                                                          
                                     };                 

                    db.Students.Add(student);                          

                    db.SaveChanges();
                }
            }
        }
        return View(model);
    }
03.04.2013
  • Спасибо ! Я так пробовал, не получается. Идентификатор «учителя» не увеличивался автоматически (все время получаю значение 0, я использую эту стратегию, это проще :: stackoverflow.com/questions/15333324/). Я получил это исключение. Невозможно определить составной порядок первичного ключа для типа «Задача». Используйте метод ColumnAttribute или HasKey, чтобы указать порядок составных первичных ключей. 03.04.2013
  • Я все еще пишу это, дайте мне секунду, и я напишу вам действие, которое работает 03.04.2013
  • Спасибо, я пробую это; Если я не ошибаюсь, нам нужно добавить public int TeacherId{ get; задавать; } к Учителю! 03.04.2013
  • @ImnotaGeek, если вы настроите свой Entities, как я показал вам, все, что вам нужно, это UserProfile = userProfile, как я сделал в Student Create Action, который вставляет UserId Foreign key в Teacher Object 03.04.2013
  • Прошу прощения ! Я не так хорош в MVC (все еще изучаю его)! Я хотел бы знать, создаете ли вы другую модель StudentViewModel или сгенерировали ее автоматически [public ActionResult Create(StudentViewModel model)]; потому что единственное исправленное утверждение, которое я здесь получил, это [public ActionResult Create(Student model)] 03.04.2013
  • вы также можете использовать public ActionResult Create(Student model), но это плохая практика, когда ваш Views общается напрямую с вашими сущностями. На данный момент все в порядке, как только вы узнаете несколько вещей, ViewModels это путь. Кроме того, не полагайтесь на генерацию кода, убедитесь, что вы изучаете Entity Framework Code First Это поможет вам лучше понять вещи, поскольку вы будете писать большую часть кода. 04.04.2013
  • Это правда. Единственная проблема, с которой мне приходится иметь дело, связана с EF/моей БД. Не удалось определить составной порядок первичного ключа для типа «Models.Tasks». Используйте метод ColumnAttribute или HasKey, чтобы указать порядок составных первичных ключей. ; Я добавляю столбец аннотации (Order = X). Это правильная стратегия! 04.04.2013
  • Я исправил проблемы с EF. После вашего ответа я понял, что пользователь еще не сохранен. Взгляните на этот снайп-шот. i.stack.imgur.com/7Xnbf.jpg 04.04.2013
  • (Теперь я могу создать профиль, но этот оператор возвращает null) [ var userProfile = db.UserProfiles.Local.SingleOrDefault(u => u.UserName == User.Identity.Name) ?? db.UserProfiles.SingleOrDefault(u => u.UserName == User.Identity.Name); ] Взгляните на этот снимок снайпита. i.stack.imgur.com/7Xnbf.jpg 04.04.2013
  • Пользователь должен войти в систему, так как мы используем User.Identity.Name 04.04.2013
  • Итак, что вы предлагаете, чтобы исправить проблему! 04.04.2013
  • Я не думаю, что это проблема, я изменил userProfile.AccountType.ToLower() на if (model.AccountType == ..) . Итак, как только мы вошли в систему, мы переходим к StudentController/TeacherController, но userProfile по-прежнему имеет значение null (потому что нам нужно проверить его еще раз, чтобы внедрить наш объект ученика). я ошибаюсь с этим анализом! 04.04.2013
  • Если пользователь физически набирает AccountType, рекомендуется использовать userProfile.AccountType.ToLower(). Если вы сделаете, как я показал вам, этот код должен работать. Причина, по которой я использовал «userProfile, а не модель», заключается в том, что мы должны получать данные от вошедшего в систему пользователя. 04.04.2013
  • Правильно. Не могли бы вы добавить в свой ответ комментарий о том, что он будет работать, если (model.AccountType == Student){..}, чтобы люди, которые будут искать решение в будущем, знали это! (Просто добавьте это как комментарий к коду). Приложение работает. Спасибо за ваше время и усилия, я ценю все это. 04.04.2013
  • Новые материалы

    React on Rails
    Основное приложение Reverb - это всеми любимый монолит Rails. Он отлично обслуживает наш API и уровень просмотра трафика. По мере роста мы добавляли больше интерактивных элементов..

    Что такое гибкие методологии разработки программного обеспечения
    Что представляют собой гибкие методологии разработки программного обеспечения в 2023 году Agile-методологии разработки программного обеспечения заключаются в следующем: И. Введение A...

    Ториго  — революция в игре Го
    Наш следующий вызов против ИИ и для ИИ. Сможет ли он победить людей в обновленной игре Го? Обратите внимание, что в следующей статье AI означает искусственный интеллект, а Goban  —..

    Простое развертывание моделей с помощью Mlflow — Упаковка классификатора обзоров продуктов NLP от HuggingFace
    Как сохранить свои модели машинного обучения в формате с открытым исходным кодом с помощью MLFlow, чтобы позже получить возможность легкого развертывания. Сегодня модели упаковки имеют несколько..

    Математика и интуиция - Часть 1
    У каждой математической формулы есть доказательство. Часто эти доказательства слишком сложно понять, поскольку многие из них основаны на индукции, некоторые - на очень сложных наблюдениях, а..

    Раскрытие возможностей НЛП: часть речевой маркировки и ее проблемы
    В сфере обработки естественного языка (NLP) маркировка частей речи (POS) выступает в качестве фундаментального метода, позволяющего компьютерам понимать и анализировать человеческий язык на..

    Под поверхностью: раскрытие деталей системы с помощью инструментов Linux CLI
    Чем больше вы изучаете Linux и продвигаетесь вперед, тем больше вам нужно проверять информацию о вашей системе. Эта информация может касаться аппаратного обеспечения, такого как процессор,..