简体   繁体   中英

ASP.NET Core - How to update existing record and insert a new one at the same time using Entity Framework

In ASP.NET Core-6 Web API Entity Framework, I want the application to perform update and insert on the same model in the database at the same time.

I have this code:

public async Task<Response<string>> CreateIdentiticationAsync(CreateIdentiticationDto model)
{
    var response = new Response<string>();
    using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
            try
            {
                var identification = _mapper.Map<Identification>(model);
                var existingIdentifications = await _dbContext.Identifications.Where(e => e.IsModified == false).ToListAsync();
                foreach (var existingIdentification in existingIdentifications)
                {
                    if (existingIdentification != null)
                    {
                        existingIdentification.IsModified = true;
                        _unitOfWork.UserIdentifications.Update(identification);
                        await _unitOfWork.Save();
                    }
                }
                Identification.IsModified = false;
                Identification.Type = model.Type;
                Identification.Name = model.Name;

                await _unitOfWork.UserIdentifications.InsertAsync(identification);
                await _unitOfWork.Save();
                response.StatusCode = (int)HttpStatusCode.Created;
                response.Successful = true;
                response.Message = "Created Successfully!";
                transaction.Complete();
                return response;
            }
            catch (Exception ex)
            {
                transaction.Dispose();
                response.Message = "An error occured";
                response.Successful = false;
                response.StatusCode = (int)HttpStatusCode.BadRequest;
                return response;
            }
    }
}

When user wants to insert a new record, I want the application to first check the model, if no record exists it should just insert the new record.

But if it exists, it should update all the IsModified to true, and then go ahead and also insert a new record.

However, when no record exists, I was able to insert new record. But where I have issue is that when it wants to update and insert new record, I got this error:

Violation of PRIMARY KEY constraint 'PK_identifications'. Cannot insert duplicate key in object 'dbo.identifications'. The duplicate key value is (81fe9b8d-2d9c-4d49-8f92-22afe043e327).

Note: Id is Guid and autgenerated

How do I resolve this?

Thanks

Many things to consider here, in modern EF, I would not use a unitOfWork also a transaction is not needed unless very specific cases, you should also validate the ID from your incoming model value is null since ID is supposed to be autogenerated (most likely this is the source of your error). Since I don't know the name of your PK field, I will not introduce such validation in my proposed code.

One last recommendation, avoid this code on your controller, it breaks Single Responsibility Principle. Create a layer where you perform your business tasks and call this layer from your controller.

Here is a simplified proposed code which should work, don't forget to ensure the value in the model ID is coming as null.

public async Task<Response<string>> CreateIdentiticationAsync(CreateIdentiticationDto model)
{
    var response = new Response<string>();
    try
    {
        var identification = _mapper.Map<Identification>(model);
        var existingIdentifications = await _dbContext.Identifications.Where(e => e.IsModified == false).ToListAsync();
        foreach (var existingIdentification in existingIdentifications)
        {
            existingIdentification.IsModified = true;
        }

        Identification.IsModified = false;

        // If you already mapped this in line 6 why map those two fields again manually?
        // Identification.Type = model.Type;
        // Identification.Name = model.Name;

        _dbContext.UpdateRange(existingIdentifications);
        _dbContext.Add(identification);
        await _dbContext.SaveChangesAsync();

        response.StatusCode = (int)HttpStatusCode.Created;
        response.Successful = true;
        response.Message = "Created Successfully!";

        return response;
    }
    catch (Exception ex)
    {
        transaction.Dispose();
        response.Message = "An error occured";
        response.Successful = false;
        response.StatusCode = (int)HttpStatusCode.BadRequest;
        return response;
    }
}
 public IActionResult Update(int? id,UpdateEmployeeVM employeeVM)
    {
        ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
        Employee existed=_context.Employees.Find(id);
        if(existed==null) { NotFound();}
        if (!_context.Positions.Any(p => p.Id == employeeVM.PositionId)) ModelState.AddModelError("PoitionId", "Choose Id right");
        if (!ModelState.IsValid)
        {
            ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
            return View();
        }
        if (employeeVM.Image!=null)
        {
            string result = employeeVM.Image.CheckValidate("image/", 300);
            if (result.Length > 0)
            {
                ViewBag.Positions=new SelectList(_context.Positions,nameof(Position.Id),nameof(Position.Name));
                ModelState.AddModelError("Image", result);
            }
            existed.ImageUrl.DeleteFile(_env.WebRootPath, "assets/img");
            existed.ImageUrl = employeeVM.Image.SaveFile(Path.Combine(_env.WebRootPath, "assets", "img"));
            

            return View();
        }
        existed.PositionId=employeeVM.PositionId;
        existed.FullName=employeeVM.FullName;
       
        existed.ImageUrl = employeeVM.Image.SaveFile(Path.Combine(_env.WebRootPath, "assets", "img"));
        
        _context.SaveChanges();
        return RedirectToAction(nameof(Index));
    }

public async Task Create(CreateEmployeeVM employeeVM)

    {
        if (!_context.Positions.Any(p => p.Id == employeeVM.PositionId)) ModelState.AddModelError("PositionId", "bele bir position yoxdu");
        if (!ModelState.IsValid)
        {
            ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
            return View();
        }
        string result = employeeVM.Image.CheckValidate(500,"image/");
        if (result.Length > 0)
        {
            ViewBag.Positions = new SelectList(_context.Positions, nameof(Position.Id), nameof(Position.Name));
            ModelState.AddModelError("Image", result);
            return View();
        }
        Employee employee = new Employee
        {
            Name = employeeVM.Name,
            Surname = employeeVM.Surname,
            PositionId = employeeVM.PositionId,
            FacebookUrl = employeeVM.FacebookUrl,
            InstagramUrl = employeeVM.InstagramUrl,
            TwitterUrl = employeeVM.TwitterUrl,
            Salary = employeeVM.Salary,
            ImageUrl = employeeVM.Image.SaveFile(Path.Combine(_env.WebRootPath, "assets", "img"))
        };
        await _context.Employees.AddAsync(employee);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM