插入到aspnetuser并将一些值插入另一个表

时间:2016-06-16 15:32:23

标签: c# asp.net-mvc entity-framework asp.net-identity dbcontext

我正在尝试从标准MVC注册表单(即电子邮件字段)插入一个值,这将是另一个表中的主键和FK。我的学生表只包含电子邮件,我想插入在注册时提交给aspnetusers表的相同值(电子邮件字段)。到目前为止我编写了这段代码:

var student = new Student { email = model.Email }; 

分配值然后

db.Students.Add(student);
db.SaveChanges(); 

执行操作,我假设这是在注册控制器中完成的。请告知我是否把它放在错误的部分。我目前正在接受

请参阅以下代码:

AccountController.cs

public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
            var student = new Student { email = model.Email };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {

                string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account");


                ViewBag.Message = "Check your email and confirm your account, you must be confirmed "
                                + "before you can log in.";
                db.Students.Add(student);
                db.SaveChanges();
                return View("Info");

                //return RedirectToAction("Index", "Home");
            }
            AddErrors(result);
        }

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

Student.cs

 public class Student
{
    [Key, ForeignKey("User")]
    public string email { get; set; }
    public virtual ApplicationUser User { get; set; }
}

3 个答案:

答案 0 :(得分:2)

此处的外键位于隐式表colum User_Id上,默认情况下为不可为空,并且您没有为User设置值以从中获取值。看起来你想要将电子邮件用作外键,但事实并非如此。外键引用相关表的主键,AspNetUsersId Email。即使你可以这样做,这也是一个非常糟糕的主意。 Email是NVARCHAR(MAX),无法编入索引。

简而言之,快速解决方法是在学生实例上设置User

var student = new Student { email = model.Email, User = user };

但是,在这里实现继承会好得多。学生是用户,所以按照这样设置:

public class Student : ApplicationUser

然后,你完全不需要这些。通过创建Student会自动生成关联的ApplicationUser,因为 ApplicationUser

<强>更新

继承时,请记住您继承了ApplicationUser上的所有属性,因此您无需再次添加Email等。如果您从上下文中提取用户,则可以使用OfType<Student>仅限学生。如果您使用ApplicationUserManager的默认实现,它将始终返回ApplicationUser个实例。但是,由于它继承自UserManager<TUser>,因此您只需修改该类以保持通用:

public class ApplicationUserManager<TUser> : UserManager<TUser>
    where TUser : ApplicationUser

为了避免修改任何现有代码,您也可以声明该类的非泛型版本:

public class ApplicationUserManager : ApplicationUserManager<ApplicationUser>
{
    public ApplicationUserManager(UserStore<ApplicationUser> store)
        : base(store)
    {
    }
}

然后,您可以构建ApplicationUserManager的不同实例,以便与您拥有的不同类型的用户一起工作。由于ApplicationUser是您的基本类型,因此如果您需要使用所有用户,则应使用该类型,例如为了进行常规登录。

答案 1 :(得分:0)

如果student.email是FK,则必须在db中存在电子邮件才能添加新学生

答案 2 :(得分:0)

Student.cs不正确。 外键指向另一个表中的PRIMARY KEY。

您可以像这样编辑Student.cs:

public class Student
{
    [Key]
    public int StudentId { get; set; }

    //Foreign key for User
    [ForeignKey("User")]
    public int UserId { get; set; }
    public virtual ApplicationUser User { get; set; }
}

如果电子邮件是唯一的,请在注册时在用户表上进行检查:

public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
     var checkEMail = db.AspNetUsers.Where(a=>a.Email == model.Email).FirstOrDefault();
     if(checkEMail != null)
      {
           //Email is not valid
      }
     else
     {              
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
            var student = new Student { email = model.Email };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {

                string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account");


                ViewBag.Message = "Check your email and confirm your account, you must be confirmed "
                                + "before you can log in.";
                db.Students.Add(student);
                db.SaveChanges();
                return View("Info");

                //return RedirectToAction("Index", "Home");
            }
            AddErrors(result);
      }

}