Q: How to check if a record with a specific ID exists in DB, avoiding " Violation of PRIMARY KEY constraint" error in a published ASP.NET Core MVC app? So I have been building a minor ASP.NET Core online shop app for a while now and a necessary part of it was to turn off the automatic ID generation in some tables. When I want to add some of the products in my shopping cart the app generates a 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. exception.
The source of it is undoubtedly the TipKreator class that initializes the database with some types for testing, which sometimes makes the app think that new types have been generated, all of which want to use the dedicated PKs.
I'm looking for a solution to check if those records exist in my EF Core database before I add them to my list.
Full error report:
BestDeal.Models.Korpa.DodajUKorpu(Artikal artikal, int kolicina) in Korpa.cs
        else
        {
            elementKorpe.KolicinaArtikla++;
        }
        try
        {
            **_context.SaveChanges();**
        }
        finally
        {
            _context.Database.CloseConnection();
        }
    }

BestDeal.Controllers.KorpaAppController.DodajKorpa(int artikalID) in 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; }
    }
}

I expect that the app doesn't crash after the changes are saved in the DB.

A: The best solution, for me, is to use the method: DbContext.Attach(object) which will try to load the related entity, based on his primary key.

If the entity is being tracked or exist, the method will retrun this object.
If not, it will begin tracking the entity.

You can also do a search with a FirstOrDefault where you will be able to know if there is any entities with the same primary key.
