Итак, я уже некоторое время создаю небольшое приложение для интернет-магазина ASP.NET Core, и необходимой его частью было отключение автоматической генерации идентификаторов в некоторых таблицах. Когда я хочу добавить некоторые товары в свою корзину, приложение генерирует исключение SqlException: Violation of PRIMARY KEY constraint 'PK_Tip'. Cannot insert duplicate key in object 'dbo.Tip'. The duplicate key value is (1).
The statement has been terminated.
.
Источником этого, несомненно, является класс TipKreator, который инициализирует базу данных с некоторыми типами для тестирования, что иногда заставляет приложение думать, что были созданы новые типы, все из которых хотят использовать выделенные PK.
Я ищу решение, чтобы проверить, существуют ли эти записи в моей базе данных EF Core, прежде чем я добавлю их в свой список.
Полный отчет об ошибке:
BestDeal.Models.Korpa.DodajUKorpu (Артикал артикал, int kolicina) в Korpa.cs
else
{
elementKorpe.KolicinaArtikla++;
}
try
{
**_context.SaveChanges();**
}
finally
{
_context.Database.CloseConnection();
}
}
BestDeal.Controllers.KorpaAppController.DodajKorpa (int artikalID) в KorpaAppController.cs
// WriteErrorLog(artikalID.ToString());
Artikal odabrani = _artikliApp.artikliApp.FirstOrDefault(p => p.IdArtikla == artikalID);
if (odabrani != null)
{
_korpica.DodajUKorpu(odabrani, 1);
}
**return RedirectToAction("Index");**
}
TipKreator.cs
public class TipKreator:ITipovi
{
List<Tip> listaTipova = new List<Tip>{new Tip { Ime = "Laptopi", idTipa = 1 },
new Tip { Ime = "Mobiteli", idTipa = 2 },
new Tip { Ime = "Računari", idTipa = 3 },
new Tip { Ime = "Računarska oprema", idTipa = 4 } };
public IEnumerable<Tip> tipoviApp
{
get {
return listaTipova;
}
}
public Tip vratiTip(string nazivTipa)
{
foreach (Tip t in listaTipova) if (t.Ime.Equals(nazivTipa)) return t;
return null; //FLAG
}
}
Korpa.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
namespace BestDeal.Models
{
//Hajmo reci da je samo lista artikala i njihovih kolicina za pocetak
//TODO: Integracija ocjena i svega
public class Korpa
{
private readonly BestDealContext _context;
//List<Tuple<Artikal, Recenzija, double>> podaciOArtiklima;
[Required]
List<KorpaInfo> artikliKolicina;
string idKorpe;
public Korpa()
{
}
public Korpa(BestDealContext context)
{
_context = context;
}
public Korpa(string idKorpe, List<KorpaInfo> artikliKolicina)
{
IdKorpe = idKorpe;
ArtikliKolicina = artikliKolicina;
}
public static Korpa DajKorpu(IServiceProvider services)
{
ISession session = services.GetRequiredService<IHttpContextAccessor>()?
.HttpContext.Session;
var context = services.GetService<BestDealContext>();
string cartId = session.GetString("idKorpe") ?? Guid.NewGuid().ToString();
session.SetString("idKorpe", cartId);
return new Korpa(context) { idKorpe = cartId };
}
public void DodajUKorpu(Artikal artikal, int kolicina)
{
var elementKorpe =
_context.KorpaInfo.SingleOrDefault(
s => s.A.IdArtikla == artikal.IdArtikla && s.IdKorpe1 == idKorpe);
if (elementKorpe == null)
{
elementKorpe = new KorpaInfo
{
IdKorpe1 = idKorpe,
A = artikal,
KolicinaArtikla = 1
};
_context.KorpaInfo.Add(elementKorpe);
}
else
{
elementKorpe.KolicinaArtikla++;
}
try
{
_context.SaveChanges();
}
finally
{
_context.Database.CloseConnection();
}
}
public int IzbaciIzKorpe(Artikal artikal)
{
var elementKorpe =
_context.KorpaInfo.SingleOrDefault(
s => s.A.IdArtikla == artikal.IdArtikla && s.IdKorpe1 == IdKorpe);
var localAmount = 0;
if (elementKorpe != null)
{
if (elementKorpe.KolicinaArtikla > 1)
{
elementKorpe.KolicinaArtikla--;
localAmount = elementKorpe.KolicinaArtikla;
}
else
{
_context.KorpaInfo.Remove(elementKorpe);
}
}
_context.SaveChanges();
return localAmount;
}
public List<KorpaInfo> DajNaruceneArtikle()
{
return artikliKolicina ??
(ArtikliKolicina =
_context.KorpaInfo.Where(c => c.IdKorpe1 == idKorpe)
.Include(s => s.A)
.ToList());
}
public void ClearCart()
{
var cartItems = _context
.KorpaInfo
.Where(cart => cart.IdKorpe1 == idKorpe);
_context.KorpaInfo.RemoveRange(cartItems);
_context.SaveChanges();
}
public decimal DajUkupnuCijenu()
{
var total = _context.KorpaInfo.Where(c => c.IdKorpe1 == idKorpe)
.Select(c => c.A.CijenaArtikla * c.KolicinaArtikla).Sum();
return (decimal)total;
}
//public List<Tuple<Artikal, Recenzija, double>> PodaciOArtiklima { get => podaciOArtiklima; set => podaciOArtiklima = value; }
[Key]
public string IdKorpe { get => idKorpe; set => idKorpe = value; }
public List<KorpaInfo> ArtikliKolicina { get => artikliKolicina; set => artikliKolicina = value; }
public void DodajArtikla(Artikal artikal, int kolicina)
{
ArtikliKolicina.Add(new KorpaInfo(artikal, kolicina));
}
}
}
KorpaAppController.cs
using BestDeal.AdapteriPodataka;
using BestDeal.Models;
using BestDeal.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
namespace BestDeal.Controllers
{
public class KorpaAppController : Controller
{
private readonly IArtikli _artikliApp;
private readonly Korpa _korpica;
public KorpaAppController(IArtikli ak, Korpa k)
{
_artikliApp = ak;
_korpica = k;
}
public ViewResult Index()
{
var items = _korpica.DajNaruceneArtikle();
_korpica.ArtikliKolicina = items;
var korpaPogled = new KorpaViewModel
{
korpa = _korpica,
UkupnaCijena = _korpica.DajUkupnuCijenu()
};
return View(korpaPogled);
}
/* public static void WriteErrorLog(string strErrorText)
{
try
{
//DECLARE THE FILENAME FROM THE ERROR LOG
string strFileName = "errorLog.txt";
string strPath = "C:\\Users\\Mirza\\Documents\\GitHub\\Grupa5-TripleDouble";
//WRITE THE ERROR TEXT AND THE CURRENT DATE-TIME TO THE ERROR FILE
System.IO.File.AppendAllText(strPath + "\\" + strFileName, strErrorText + " - " + DateTime.Now.ToString() + "\r\n");
}
catch (Exception ex)
{
WriteErrorLog("Error in WriteErrorLog: " + ex.Message);
}
}*/
public RedirectToActionResult DodajKorpa(int artikalID)
{
// WriteErrorLog(artikalID.ToString());
Artikal odabrani = _artikliApp.artikliApp.FirstOrDefault(p => p.IdArtikla == artikalID);
if (odabrani != null)
{
_korpica.DodajUKorpu(odabrani, 1);
}
return RedirectToAction("Index");
}
public RedirectToActionResult BrisiKorpa(int artikalID)
{
var odabrani = _artikliApp.artikliApp.FirstOrDefault(p => p.IdArtikla == artikalID);
if (odabrani != null)
{
_korpica.IzbaciIzKorpe(odabrani);
}
return RedirectToAction("Index");
}
}
}
Tip.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace BestDeal.Models
{
//klasa koja omogucava dodavanje tipova
public class Tip
{
public Tip()
{
}
//TODO:Moguce opcije nekog IDa ili liste specificnih polja koju ima svaki tip (radi razlicitih detalja kod recenzija i sl.)
public Tip(string ime)
{
Ime = ime;
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int idTipa { get; set; }
public string Ime { get; set; }
public override bool Equals(object obj)
{
var other = obj as Tip;
if (other == null)
{
return false;
}
return other == this;
}
public override int GetHashCode()
{
return HashCode.Combine(idTipa);
}
public static bool operator ==(Tip Tip1, Tip Tip2)
{
if (Object.ReferenceEquals(Tip1, null) && Object.ReferenceEquals(Tip2, null))
return true;
if (Object.ReferenceEquals(Tip1, null) || Object.ReferenceEquals(Tip2, null))
return false;
return Tip1.Ime == Tip2.Ime;
}
public static bool operator !=(Tip Tip1, Tip Tip2)
{
return !(Tip1 == Tip2);
}
}
}
KorpaInfo.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace BestDeal.Models
{
public class KorpaInfo:Korpa
{
string idKorpe;
Artikal a;
int kolicinaArtikla;
int idKomponente;
public KorpaInfo()
{
}
public KorpaInfo(Artikal a, int kolicinaArtikla)
{
this.A = a;
this.KolicinaArtikla = kolicinaArtikla;
}
public KorpaInfo(string idKorpe, Artikal a, int kolicinaArtikla)
{
this.idKorpe = idKorpe;
this.a = a;
this.kolicinaArtikla = kolicinaArtikla;
}
public Artikal A { get => a; set => a = value; }
public int KolicinaArtikla { get => kolicinaArtikla; set => kolicinaArtikla = value; }
public string IdKorpe1 { get => idKorpe; set => idKorpe = value; }
}
}
Я ожидаю, что приложение не аварийно завершит работу после сохранения изменений в БД.