Reputation: 376
Service:
public Cart AddProductToCart(Product product, Cart cart)
{
var productExist = _dbContexet.CartProduct.Where(cp => cp.ProductId == product.Id).FirstOrDefault();
var quantityOfCart = _dbContexet.CartProduct.Where(cp => cp.CartId == cart.Id).FirstOrDefault().Quantity;
CartProduct cartProduct = new CartProduct();
cartProduct.CartId = cart.Id;
cartProduct.ProductId = product.Id;
if (productExist != null)
{
cartProduct.Quantity = quantityOfCart + 1;
_dbContexet.Attach(cartProduct).State = EntityState.Modified;
}
else
{
cartProduct.Cart = cart;
cartProduct.Product = product;
_dbContexet.CartProduct.Add(cartProduct);
}
_dbContexet.SaveChanges();
return cart;
}
Full error:
InvalidOperationException: The instance of entity type 'CartProduct' cannot be tracked because another instance with the same key value for {'CartId', 'ProductId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
I have many to many and table CartProduct
I want to check if product exist and only update quantity if it exist but I get this error?
Eddit:
Product:
public partial class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public decimal CostToMake { get; set; }
public decimal FinalPrice { get; set; }
//public int? OrderId { get; set; }
public virtual Order Order { get; set; }
public List<CartProduct> CartProduct { get; set; }
}
Cart:
public class Cart
{
public int Id { get; set; }
public int ProductCount { get; set; }
public AppUser User { get; set; }
public List<CartProduct> CartProduct { get; set; }
}
CartProduct:
public class CartProduct
{
public int CartId { get; set; }
public int ProductId { get; set; }
public Cart Cart { get; set; }
public Product Product { get; set; }
public int Quantity { get; set; }
}
FluentAPI:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasAnnotation("Relational:Collation", "Cyrillic_General_CI_AS");
modelBuilder.Entity<Day>(entity =>
{
entity.Property(e => e.Date).HasColumnType("date");
entity.Property(e => e.MostCommonCategory)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.MostCommonProduct)
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.TotalMade).HasColumnType("decimal(18, 3)");
entity.Property(e => e.TotalSpent).HasColumnType("decimal(18, 3)");
});
modelBuilder.Entity<Order>(entity =>
{
entity.Property(e => e.Date).HasColumnType("date");
entity.Property(e => e.Status)
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.Name).HasMaxLength(100);
entity.Property(e => e.Address).HasMaxLength(150);
entity.Property(e => e.PhoneNumber).HasMaxLength(20);
});
modelBuilder.Entity<Product>(entity =>
{
entity.HasIndex(e => e.OrderId, "IX_Products_OrderId");
entity.Property(e => e.Category)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.CostToMake).HasColumnType("decimal(18, 3)");
entity.Property(e => e.FinalPrice).HasColumnType("decimal(18, 3)");
entity.Property(e => e.Name)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.Price).HasColumnType("decimal(18, 3)");
entity.HasOne(d => d.Order)
.WithMany(p => p.Products)
.HasForeignKey(d => d.OrderId);
});
modelBuilder.Entity<Cart>(entity => {
entity.HasKey(e => e.Id);
entity.HasOne(e => e.User)
.WithOne(e => e.Cart)
.HasForeignKey<AppUser>(e => e.CartId);
});
modelBuilder.Entity<CartProduct>()
.HasKey(e => new { e.CartId, e.ProductId });
modelBuilder.Entity<CartProduct>()
.HasOne(t => t.Cart)
.WithMany(t => t.CartProduct)
.HasForeignKey(t => t.ProductId);
modelBuilder.Entity<CartProduct>()
.HasOne(t => t.Product)
.WithMany(t => t.CartProduct)
.HasForeignKey(t => t.CartId);
OnModelCreatingPartial(modelBuilder);
}
Upvotes: 1
Views: 820
Reputation: 1026
You can perform some actions but in a different way, using EF features.
public Cart AddProductToCart(Product product, Cart cart)
{
var product = _dbContexet.Product.Where(cp => cp.ProductId == product.Id).Include(x => x.CartProduct).FirstOrDefault();
var quantityOfCart = _dbContexet.CartProduct.Where(cp => cp.CartId == cart.Id).FirstOrDefault().Quantity;
var cartProduct = product.CartProduct.Where(x=>x.CartId == cart.id).FirstOrDefault();
if (cartProduct != null)
{
cartProduct.Quantity = quantityOfCart + 1;
}
else
{
product.CartProduct.Add(new CartProduct { CartId = cart.id });
}
//_dbContexet.Update(product) if you are using QueryTrackingBehavior.NoTracking
_dbContexet.SaveChanges();
return cart;
}
Upvotes: 2
Reputation: 43870
Your error is because :
cartProduct.CartId = cart.Id;
cartProduct.ProductId = product.Id;
in reallity is the same as:
cartProduct.Cart = cart;
cartProduct.Product = product;
so just remove from your code:
cartProduct.Cart = cart;
cartProduct.Product = product;
Upvotes: 0