EF - checking that an user cannot enter twice the same key - 12 pgms - 8 working well, 4 send an system error msg !!!

Dmtr_Grms 331 Reputation points
2022-08-05T17:45:19.4+00:00

Could someone help me? How to catch that kind of exception? I cannot find the InnerException message number as for example with DBupdateException.
Thanks in advance for your help.

Error msg: System.InvalidOperationException: 'The instance of entity type 'Country' cannot be tracked because another instance with the same key value for {'CountryName'} 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.'

class:
using System.ComponentModel.DataAnnotations;
using System;
using System.Collections.Generic;

namespace ATChome.DbModel
{
public class Country
{
public int CountryId { get; set; }

    public string CountryName { get; set; }  

    public string CountryIso { get; set; }  

    public bool IsDeleted { get; set; }  

    public int UserIdCrea { get; set; }  

    public DateTime DateCreation { get; set; }  

    public int UserIdMod { get; set; }  

    public DateTime DateModification { get; set; }  

    public byte[] Timestamp { get; set; }  


    // Relationship Collection Navigation Property  
    public List<Postalinfo> Postalinfos { get; set; }  
}  

}

DBContext:
public DbSet<Country>? Countries { get; set; }
// COUNTRY Table
modelBuilder.Entity<Country>().HasKey(c => c.CountryId);
modelBuilder.Entity<Country>().HasIndex(c => c.CountryName).IsUnique();
modelBuilder.Entity<Country>().Property(c => c.CountryName).HasMaxLength(60);
modelBuilder.Entity<Country>().Property(c => c.CountryIso).HasMaxLength(3);
modelBuilder.Entity<Country>().Property(c => c.IsDeleted).HasDefaultValue(0);
modelBuilder.Entity<Country>().Property(c => c.UserIdCrea);
modelBuilder.Entity<Country>().Property(c => c.DateCreation).HasDefaultValueSql("getdate()");
modelBuilder.Entity<Country>().Property(c => c.UserIdMod);
modelBuilder.Entity<Country>().Property(c => c.DateModification).HasDefaultValueSql("getdate()");
modelBuilder.Entity<Country>().Property(c => c.Timestamp).IsRowVersion();

Program C#:
using ATChome.DbModel;
using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
// Imports necessary to add
using System.Windows.Data;
using Microsoft.Data.SqlClient;

namespace ATChome
{
/// <summary>
/// Interaction logic for PageCountries.xaml
/// </summary>
public partial class PageCountries : Window
{
// Context initialization
private readonly AtcDbContext context = new();
Country NewCountry = new();

    // WARNING - put readonly in order to avoid message from compiler controls  
    private readonly CollectionViewSource countryViewSource;  


    public PageCountries()  
    {  
        this.context = context;  
        InitializeComponent();  
        countryViewSource = (CollectionViewSource)FindResource(nameof(countryViewSource));  
        GvAdd.DataContext = NewCountry;  
    }  

    private void Window_Loaded(object sender, RoutedEventArgs e)  
    {  
        // Load the entities into EF Core  
        context.Countries.Load();  

        // Binding to the source  
        countryViewSource.Source = context.Countries.Local.ToObservableCollection();  
    }  

    // Filters Box Collection and Refresh Management  

    // Filter on CountryName  
    private void TxtCountryName_TextChanged(object sender, TextChangedEventArgs e)  
    {  
        // Refresh the view to apply filters.  
        CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
    }  
    // Filter on CountryIso  
    private void TxtCountryIso_TextChanged(object sender, TextChangedEventArgs e)  
    {  
        // Refresh the view to apply filters.  
        CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
    }  
    // Filter on IsDeleted refresh  
    private void IsDeletedFilter_Changed(object sender, RoutedEventArgs e)  
    {  
        // Refresh the view to apply filters.  
        CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
    }  
    private void CollectionViewSource_Filter(object sender, FilterEventArgs e)  
    {  
        int refused = 0;  
        if (e.Item is Country t && t != null) /* If filters have value, process filters.  
                                                 WARNING introduced comparison type for Culture params and NON sensitive Case */  
        {  
            if (this.TxtCountryName != null && t.CountryName != null && t.CountryName.Contains(TxtCountryName.Text, StringComparison.CurrentCultureIgnoreCase) == false)  
            {  
                refused++;  
            }  
            if (this.TxtCountryIso != null && t.CountryIso != null && t.CountryIso.Contains(TxtCountryIso.Text, StringComparison.CurrentCultureIgnoreCase) == false)  
            {  
                refused++;  
            }  
            if (this.CbIsDeletedFilter.IsChecked == false && t.IsDeleted == true)  
            {  
                refused++;  
            }  
            if (refused == 0)  
            {  
                e.Accepted = true;  
            }  
            else  
            {  
                e.Accepted = false;  
            }  
        }  
    }  
    // - Event handler for Selection in DataGrid -   
    private void DataGridList_SelectionChanged(object sender, SelectionChangedEventArgs e)  
    {  
        if (e.AddedItems.Count > 0)  
        {  
            Country country = (Country)e.AddedItems[0];  
            if (country.IsDeleted == true)  
            {  
                DataGridList.SelectedItem = null;  
                CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
                MessageBox.Show("Non è possibile modificare un Paese cancellato", "ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
                return;  
            }  
        }  
    }  


    //Event handler for the UI Update Button in Tabcontrol.  
    private void BtnUpdate1_Click(object sender, RoutedEventArgs e)  
    {  
        int mistakeinupdate = 0;  

        if (string.IsNullOrWhiteSpace(TxtCountryName1.Text))  
        {  
            mistakeinupdate = 1;  
            MessageBox.Show("Inserire un nome Paese per favore", "ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
        }  
        if (string.IsNullOrWhiteSpace(TxtCountryIso1.Text))  
        {  
            mistakeinupdate = 2;  
            MessageBox.Show("Inserire un Codice ISO per favore", "ATC - ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
        }  


        if (mistakeinupdate == 0)  
        {  
            // Before Save in DB - Context Update because trigger choice in XAML is Explicit !  
            BindingExpression be1 = TxtCountryName1.GetBindingExpression(TextBox.TextProperty);  
            be1.UpdateSource();  
            BindingExpression be2 = TxtCountryIso1.GetBindingExpression(TextBox.TextProperty);  
            be2.UpdateSource();  

            try  
            {  
                context.SaveChanges();  
                // Deselect Item and Refresh all views .  
                DataGridList.SelectedItem = null;  
                CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
                MessageBox.Show("Paese modificato correttamente", "ATC - CONFERMA", MessageBoxButton.OK, MessageBoxImage.Information);  

            }  
            catch (DbUpdateException)  
            {  
                MessageBox.Show("Problema aggiornamento DataBase in modifica", "ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
            }  
            catch (DBConcurrencyException ex)  
            {  
                MessageBox.Show("Non posso aggiornare il DataBase un altro utente lo sta modificando, riprovare per favore", "ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
                // Deselect Item and Refresh all views .  
                DataGridList.SelectedItem = null;  
                CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
            }  
        }  
        else  
        {  
            return;  
        }  
    }  

    //Event handler for the UI Add Button in Tabcontrol.  
    private void BtnAdd0_Click(object sender, RoutedEventArgs e)  
    {  
        // Initialization  

        // Check data coming from ADD GUI  
        int mistakeinadd = 0;  

        if (string.IsNullOrWhiteSpace(TxtCountryName0.Text))  
        {  
            mistakeinadd = 1;  
            MessageBox.Show("Inserire un nome Paese per favore", "ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
        }  
        if (string.IsNullOrWhiteSpace(TxtCountryIso0.Text))  
        {  
            mistakeinadd = 2;  
            MessageBox.Show("Inserire un Codice ISO per favore", "ATC - ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
        }  
        // Insert in Database  
        if (mistakeinadd == 0)  
        {  
            try  
            {  
                ****context.Countries.Add(NewCountry);** LINE THAT GIVES ERROR!!!!!!!!!!!!**  
                context.SaveChanges();  
                DataGridList.SelectedItem = null;  
                CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
                NewCountry = new Country();  
                GvAdd.DataContext = NewCountry;  
                MessageBox.Show("Paese aggiunto correttamente", "ATC - CONFERMA", MessageBoxButton.OK, MessageBoxImage.Information);  
            }  
            catch (DbUpdateException ex)  
            {  
                if (ex.InnerException is SqlException sqlException)  
                {  
                    switch (sqlException.Number)  
                    {  
                        case 2601: // Unique Key violation exception code  
                            context.Countries.Remove(NewCountry);  
                            MessageBox.Show("Paese già esistente", "ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
                            break;  
                        default:  
                            context.Countries.Remove(NewCountry);  
                            MessageBox.Show("Problema aggiornamento DataBase, contattare supporto", "ATC - ERRORE", MessageBoxButton.OK, MessageBoxImage.Error);  
                            break;  
                    }  
                }  
            }  
        }  
        else  
        {  
            return;  
        }  
    }  
    // Event handler for the UI Logical Cancel Button in Tabcontrol.  
    private void BtnCancel1_Click(object sender, RoutedEventArgs e)  
    {  
        if (string.IsNullOrWhiteSpace(TxtCountryName1.Text))  
        {  
            return;  
        }  
        else  
        {  
            if (MessageBox.Show("Cancellare il Paese ?", "ATC - CONFERMA", MessageBoxButton.YesNo, MessageBoxImage.Exclamation) == MessageBoxResult.Yes)  
            {  
                CbIsDeleted1.IsChecked = true;  
                context.SaveChanges();  
                // Deselect Item and Refresh all views .  
                DataGridList.SelectedItem = null;  
                CollectionViewSource.GetDefaultView(DataGridList.ItemsSource).Refresh();  
                MessageBox.Show("Paese cancellato", "ATC - CONFERMA", MessageBoxButton.OK, MessageBoxImage.Information);  

            }  
            else  
            {  
                return;  
            }  
        }  
    }  
    // CLOSING Procedure  
    //Close current PageCountries page with Button.  
    private void ClosePageCountries_Click(object sender, RoutedEventArgs e)  
    {  
        context.Dispose();  
        this.Close();  
    }  

    // Clean up connections when closing window.  
    protected override void OnClosing(CancelEventArgs e)  
    {  
        // clean up database connections  
        context.Dispose();  
    }  

}  

}

Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
696 questions
{count} votes