如何从表格中获取最后插入的ID(String)

时间:2018-11-18 19:38:46

标签: sql-server asp.net-mvc entity-framework

我想使用数据库中最后插入的ID,但是该ID为字符串格式。有什么方法可以获取最后插入的字符串ID?

每次使用

p.UserId = db.AspNetUsers.Max(m => m.Id);

,但返回错误结果。我认为这是字符串,因此max无法使用。有人可以建议如何解决这个问题吗?

表结构:

  • 患者:ID(PK),UID(UserLogin的fk),名称

AspNetUsers 表:

CREATE TABLE [dbo].[AspNetUsers] 
(
    [Id]    NVARCHAR(128) NOT NULL,
    [Email] NVARCHAR (256) NULL,
)

患者表:

CREATE TABLE Patient
(
     PatientId INT IDENTITY(1,1) PRIMARY KEY,
     PId AS 'P' + RIGHT('00000' + CAST(PatientId AS NVARCHAR(10)), 10) PERSISTED,
     UserId NVARCHAR(128) FOREIGN KEY REFERENCES AspNetUsers(Id)
)

示例ID的格式如下:62d8d072-5261-4aaf-b552-d75453cc3421

这是代码,首先我从AspNetUsers表的视图中获取值,因此它将在表中生成ID,并且我想将该ID用于我的Patient表。

[HttpPost]
[ValidateAntiForgeryToken]
[AllowAnonymous]
public async Task<ActionResult> SignUp(Patientview pv)
{
        ClinicDbContext db = new ClinicDbContext();

        if (ModelState.IsValid)
        {
            try
            {
                var user = new ApplicationUser { UserName = pv.Email, Email = pv.Email };
                var result = await UserManager.CreateAsync(user, pv.Password);

                if (result.Succeeded)
                {
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

                }
                else
                {
                    return View(pv);
                }

                Patient p = new Patient();
                p.FirstName = pv.FirstName;
                p.LastName = pv.LastName;
                p.DateOfBirth = pv.DateOfBirth;
                p.Email = pv.Email;
                p.PhoneNumber = pv.PhoneNumber.ToString();
                p.StreetAddress = pv.StreetAddress.ToString();
                p.City = pv.City;
                p.State = pv.State;
                p.ZipCode = pv.ZipCode;
                p.UserId = db.AspNetUsers.Max(m => m.Id);

                _context.Patients.Add(p);
                _context.SaveChanges();

                return RedirectToAction("Index", "Admin");
            }
            catch (DbEntityValidationException e)
            {
                foreach (var eve in e.EntityValidationErrors)
                {
                    System.Diagnostics.Debug.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                        eve.Entry.Entity.GetType().Name, eve.Entry.State);
                    foreach (var ve in eve.ValidationErrors)
                    {
                        System.Diagnostics.Debug.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
                            ve.PropertyName, ve.ErrorMessage);
                    }
                }
                throw;
            }
        }
        else
        {
            return View(pv);
        }
}

2 个答案:

答案 0 :(得分:0)

通常,使用EF可以映射实体与FK的关系,并在保存主记录和关联记录时让EF管理FK的分配。但是,在您的情况下,这种关系是相对松散的。

所有患者记录是否都将与ASP.Net身份验证用户相关联?如果是这样,您可以查看更改Patient上的PK类型以匹配ASPNet表,然后将Patient设置为与ASPNetUser一对一的关系。

或者,如果患者可以是ASPNetUsers(但也可以分离),那么我会考虑将PatientId列作为自动递增的整数或顺序GUID(newsequentialId())添加到ASPNetUser,并将其映射为Patient可选或要求多对一。这避免了ASPNetUser上字符串PK的麻烦,并允许您使用更适合您的应用程序的FK类型。 (整数或GUID)

您可以用来获取新插入的PK的第三个选项; PK将仅在DbContext SaveChanges之后创建,因此,您需要两次调用SaveChanges以获得第一个ID:

//...
var user = new ApplicationUser { UserName = pv.Email, Email = pv.Email };
var result = await UserManager.CreateAsync(user, pv.Password);

if (result.Succeeded)
  await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
else
  return View(pv);

_context.SaveChanges();
Patient p = new Patient();
p.PatientId = Guid.Parse(user.UserId); // User ID will be populated after the above SaveChanges call.                
p.FirstName = pv.FirstName;
//...
_context.SaveChanges(); //Save the Patient.

通常这不是很理想,因为您可以得到第一个SaveChanges成功但第二个SaveChanges成功的情况。这些记录可能应该一起处理,因此可以通过事务范围或诸如DbContextScope之类的单元或工作来实现。

使用TransactionScope:

using (var tx = new TransactionScope())
{ 
    var user = new ApplicationUser { UserName = pv.Email, Email = pv.Email };
    var result = await UserManager.CreateAsync(user, pv.Password);

    if (result.Succeeded)
      await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
    else
      return View(pv);

    _context.SaveChanges();
    Patient p = new Patient();
    p.PatientId = Guid.Parse(user.UserId); // User ID will be populated after the above SaveChanges call.                
    p.FirstName = pv.FirstName;
    //...
    _context.SaveChanges(); //Save the Patient.

  tx.Complete()
}

但是,一般来说,映射实体之间的关系是一个更好的选择,因为这样可以设置FK约束来管理级联删除之类的事情。

答案 1 :(得分:-1)

我了解您要获取数据库中最后插入的字段。

为什么不使用Last()函数。 :)

p.UserId = db.AspNetUsers.Select(X=>x.id).Last(); 

将从表格的最后一行为您提供Userid。

Max正在选择可能会或可能不会产生最后一个值的最大值。