Я кодирую небольшую службу под названием Cart.API
, которая должна обрабатывать все запросы на добавление / обновление / удаление в моей базе данных (я использую docker, поэтому я размещаю базу данных MSSQL в контейнере Docker).Прямо сейчас я застрял в методе DeleteCatalogItemAsync
.
Это код CartController.cs
:
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Cart.API.Models;
using Cart.API.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace Cart.API.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class CartController : ControllerBase
{
private readonly CartContext _context;
private readonly ICartService _cartService;
private readonly ICatalogService _catalogService;
public CartController(CartContext context, ICartService cartService, ICatalogService catalogService)
{
_context = context;
_cartService = cartService;
_catalogService = catalogService;
}
[HttpGet]
[Route("cart/{id}")]
public bool CartExists(int id)
{
return _context.UserCarts.Any(cart => cart.Id == id);
}
[HttpGet]
[Route("entries")]
public async Task<ActionResult<List<CartModel>>> GetAllCartAsync()
{
var cartList = await _context.UserCarts.Include(cart => cart.Items).ToListAsync(); //include needed to load Items List
if (cartList == null)
{
return NoContent();
}
return cartList;
}
[HttpGet]
[Route("entries/{id}")]
public async Task<ActionResult<CartModel>> GetCartByIdAsync(int id)
{
var cart = await _context.UserCarts.Where(b => b.Id == id).Include(m => m.Items).SingleOrDefaultAsync();
return cart ?? new CartModel(id);
}
[HttpPut]
[Route("entries")]
public async Task<ActionResult> AddCartItemAsync([FromBody] AddCartItemRequest requestItem)
{
if (requestItem == null || requestItem.Quantity == 0)
{
return BadRequest("Invalid payload");
}
//Check, if cart already exists or a new one has to be added
var cartExists = await _cartService.CheckCartExistance(requestItem.CartId);
//Get or create cart object by the requested Id
var currentCart = await _cartService.GetCartByIdAsync(requestItem.CartId);
//Get Catalog Item
var catalogItem = await _catalogService.GetCatalogItemByIdAsync(requestItem.CatalogItemId);
currentCart.Items.Add(new CartItem(catalogItem.Id, catalogItem.Name, catalogItem.Price, requestItem.Quantity));
if (!cartExists)
{
_context.UserCarts.Add(currentCart);
}
else
{
_context.UserCarts.Update(currentCart);
}
await _context.SaveChangesAsync();
return Ok(currentCart);
}
[HttpDelete]
[Route("entries/remove")]
public async Task<ActionResult> DeleteCatalogItemAsync([FromBody] DeleteCartItemRequest requestItem)
{
if (requestItem == null)
{
return BadRequest("Cannot perform action");
}
//Check if Basket exists
var basketExists = await _cartService.CheckCartExistance(requestItem.CartId);
if (basketExists)
{
//var currentCart = await _context.UserCarts.Include(model => model.Items).SingleOrDefaultAsync(model => model.Id == requestItem.CartId);
var currentCart = await _cartService.GetCartByIdAsync(requestItem.CartId);
if(currentCart != null)
{
var itemToDelete = currentCart.Items.Find(model => model.ProductId == requestItem.CatalogItemId);
currentCart.Items.Remove(itemToDelete);
//currentCart.RemoveCartItem(requestItem.CatalogItemId);
_context.UserCarts.Update(currentCart);
await _context.SaveChangesAsync();
return Ok();
}
return BadRequest("Das Item mit der ID " + requestItem.CatalogItemId + " konnte nicht gelöscht werden.");
}
return NotFound("Es existiert kein Warenkorb mit der ID " + requestItem.CartId);
}
[HttpGet]
[Route("test")]
public async Task<ActionResult> TestCall()
{
var test1 = await _catalogService.GetCatalogItemByIdAsync(1);
return Ok(test1);
}
}
}
CartService.cs
:
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Cart.API.Models;
using Newtonsoft.Json;
namespace Cart.API.Services
{
public class CartService : ICartService
{
private readonly HttpClient _client;
public CartService(HttpClient client)
{
_client = client;
}
public async Task<IEnumerable<CartModel>> GetAllCartsAsync()
{
var stringContent = await _client.GetStringAsync("http://cart.api/api/cart/entries");
return JsonConvert.DeserializeObject<List<CartModel>>(stringContent);
}
public async Task<CartModel> GetCartByIdAsync(int id)
{
var stringContent = await _client.GetStringAsync("http://cart.api/api/cart/entries/" + id);
var cart = !string.IsNullOrEmpty(stringContent) ? JsonConvert.DeserializeObject<CartModel>(stringContent) : null;
return cart;
}
public async Task<bool> CheckCartExistance(int cartId)
{
var stringContent = await _client.GetStringAsync("http://cart.api/api/cart/cart/" + cartId);
return JsonConvert.DeserializeObject<bool>(stringContent);
}
}
}
CartModel.cs
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace Cart.API.Models
{
public class CartModel
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public List<CartItem> Items { get; set; }
public CartModel(int id)
{
Id = id;
Items = new List<CartItem>();
}
public bool RemoveCartItem(int id)
{
var itemToDelete = Items.Find(m => m.ProductId == id);
return Items.Remove(itemToDelete);
}
}
}
CartItem.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Cart.API.Models
{
public class CartItem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public long ProductId { get; set; }
public string ProductName { get; set; }
public double ProductPrice { get; set; }
public int ProductQuantity { get; set; }
public CartItem(long productId, string productName, double productPrice, int productQuantity)
{
ProductId = productId;
ProductName = productName;
ProductPrice = productPrice;
ProductQuantity = productQuantity;
}
}
}
Итак, в методе DeleteCatalogItemAsync
из CartController.cs
я пытаюсь предоставить функциональность, чтобы иметь возможностьудалить существующий CatalogItem.Поэтому я вызываю cartService, чтобы получить корзину, из которой должен быть удален элемент, прежде чем я на самом деле удаляю CatalogItem из списка корзины.Моя проблема в том, что с предоставленным кодом выше, CatalogItem не удаляется из базы данных, потому что изменения в объекте currentCart так или иначе не сохраняются в базе данных.Насколько я знаю, объект currentCart не отслеживается, поэтому перед сохранением объекта в базе данных я вызываю метод .Update, чтобы начать отслеживание элемента и пометить все свойства как измененные.
var itemToDelete = currentCart.Items.Find(model => model.ProductId == requestItem.CatalogItemId);
currentCart.Items.Remove(itemToDelete);
_context.UserCarts.Update(currentCart);
await _context.SaveChangesAsync();
Iпоигрался с порядком кода сверху, и каким-то образом сохранение измененного объекта в dababase работает с таким порядком кода:
var itemToDelete = currentCart.Items.Find(model => model.ProductId == requestItem.CatalogItemId);
_context.UserCarts.Update(currentCart);
currentCart.Items.Remove(itemToDelete);
await _context.SaveChangesAsync();
Почему работает это решение, а не первое?