none
error : an attempt was made to remove a relationship between

    Question

  • Hi all,

    I got an error on my application when I try to add or delete an entity 'Prêt' after deleting another one.

    In my local DB I have the following entities : Utilisateur (having from 0:N) Contacts (having from 0:N) Prêts

    At the beginning, I can add as many contacts and prêts on these contacts as I want. However, as soon as I proceed to a delete (on a Prêt), this delete is executed correctly but after that I can't perform any new add or delete of a Prêt, because I got the following error message:

    "An attempt was made to remove a relationship between a Utilisateur and a Contact. However, one of the relationship's foreign keys (Contact._fkutilisateurId) cannot be set to null."string

    I try to modify my code in many ways but did not manage to solve my issue.

    Hereunder is my ContactViewModel:

    namespace MesEchanges.ViewModel
    {
        public class AccueilContactViewModel : ViewModelBase
        {
            #region Données
     
            // LINQ to SQL data context for the local database.
            private MesEchangesDataContext mesEchangesDB;
     
            #endregion
     
            #region Constructeur
     
            public AccueilContactViewModel(string mesEchangesDBConnectionString)
            {
                mesEchangesDB = new MesEchangesDataContext(mesEchangesDBConnectionString);
            }
     
            #endregion
     
            #region Getter et setter liés aux données de la DB
     
            private Contact _contact;
            public Contact Contact
            {
                get { return _contact; }
                set { NotifyPropertyChanged(ref _contact, value); }
            }
     
            private Utilisateur _utilisateur;
            public Utilisateur Utilisateur
            {
                get { return _utilisateur; }
                set { NotifyPropertyChanged(ref _utilisateur, value); }
            }
     
            private ObservableCollection<Types> _typesListe;
            public ObservableCollection<Types> TypesListe
            {
                get { return _typesListe; }
                set { NotifyPropertyChanged(ref _typesListe, value); }
            }
     
            private ObservableCollection<Categories> _categoriesListe;
            public ObservableCollection<Categories> CategoriesListe
            {
                get { return _categoriesListe; }
                set { NotifyPropertyChanged(ref _categoriesListe, value); }
            }
             
            private ObservableCollection<Pret> _pretsListe;
            public ObservableCollection<Pret> PretsListe
            {
                get { return _pretsListe; }
                set { NotifyPropertyChanged(ref _pretsListe, value); }
            }
     
            private ObservableCollection<Pret> _empruntsListe;
            public ObservableCollection<Pret> EmpruntsListe
            {
                get { return _empruntsListe; }
                set { NotifyPropertyChanged(ref _empruntsListe, value); }
            }
     
            private Categories _categorie;
            public Categories Categorie
            {
                get { return _categorie; }
                set { NotifyPropertyChanged(ref _categorie, value); }
            }
     
            private Types _type;
            public Types Type
            {
                get { return _type; }
                set { NotifyPropertyChanged(ref _type, value); }
            }
     
            #endregion
     
            #region Fonctions
     
            #region Mise en place de la fonction NotifyPropertyChanged<T>
     
            private bool NotifyPropertyChanged<T>(ref T variable, T valeur, [CallerMemberName] string nomPropriete = null)
            {
                if (object.Equals(variable, valeur)) return false;
     
                variable = valeur;
                RaisePropertyChanged(nomPropriete);
                return true;
            }
     
            #endregion
     
            // Ecrire les changements du datacontext dans la base de données.
            public void SaveChangesToDB()
            {
                mesEchangesDB.SubmitChanges();
            }
     
            // Requêtes en base et chargement des collections utilisées par les collections des pivot pages.
            public void LoadCollectionsFromDatabase()
            {
                int contactId = (int)IsolatedStorageSettings.ApplicationSettings["contactId"];
                //int utilisateurId = (int)IsolatedStorageSettings.ApplicationSettings["utilisateurId"];
     
                Contact = mesEchangesDB.Contact.Single(c => c.ContactId == contactId);
                // Sauvegarde du contact dans l'isolatedstorage pour l'utiliser lors de l'association avec le nouveau prêt.
                IsolatedStorageSettings.ApplicationSettings["contact"] = Contact;
     
                Utilisateur = mesEchangesDB.Utilisateur.First();
                var liste = mesEchangesDB.Pret.Where(p => p._fkcontactId == Contact.ContactId);
     
                Categorie = mesEchangesDB.Categorie.Single(c => c.Categorie == "Argent");
                Type = mesEchangesDB.Type.Single(t => t.Type == "Prêt");
     
                PretsListe = new ObservableCollection<Pret>();
                EmpruntsListe = new ObservableCollection<Pret>();
     
                foreach (Pret pret in liste)
                {
                    switch (pret.Type.Type)
                    {
                        case "Prêt":
                            PretsListe.Add(pret);
                            break;
                        case "Emprunt":
                            EmpruntsListe.Add(pret);
                            break;
                    }
                }
     
                // Définir la requêtes pour toutes les catégories de la base de données
                var categorieInDB = from Categories categorie in mesEchangesDB.Categorie
                                    select categorie;
     
                // Requêter la base de données et charger toutes les catégories
                CategoriesListe = new ObservableCollection<Categories>(categorieInDB);
     
                // Définir la requêtes pour toutes les catégories de la base de données
                var typeInDB = from Types type in mesEchangesDB.Type
                                    select type;
     
                // Requêter la base de données et charger toutes les catégories
                TypesListe = new ObservableCollection<Types>(typeInDB);
            }
     
            // Ajout d'un prêt à la base de données et à la collection.
            public void AddPret(Pret newPret)
            {
                // Ajout d'un prêt au data context.
                mesEchangesDB.Pret.InsertOnSubmit(newPret);
     
                // Mise à jour des données du contact
                if (newPret.Categorie.Categorie == "Argent")
                {
                    Contact.calculMontant(newPret.Type.Type, newPret.Montant, "ajout");
                    Utilisateur.calculMontant(newPret.Type.Type, newPret.Montant, "ajout");
                }
                else
                {
                    Contact.calculObjet(newPret.Type.Type, "ajout");
                    Utilisateur.calculObjet(newPret.Type.Type, "ajout");
                }
     
                // Sauvegarde des changements dans la base de données.
                mesEchangesDB.SubmitChanges();
                 
                if (newPret.Type.Type == "Prêt")
                {
                    // Ajout du prêt à la "PretsListe" observable collection.
                    PretsListe.Add(newPret);
                }
                else if (newPret.Type.Type == "Emprunt")
                {
                    // Ajout du prêt à la "PretsListe" observable collection.
                    EmpruntsListe.Add(newPret);
                }
            }
     
            // Suppression d'un prêt de la base de données et de la collection.
            public void DeletePret(Pret pretForDelete)
            {
                // Suppression du prêt du data context.
                mesEchangesDB.Pret.DeleteOnSubmit(pretForDelete);
                Contact.Pret.Remove(pretForDelete);
     
                if (pretForDelete.Categorie.Categorie == "Argent")
                {
                    Contact.calculMontant(pretForDelete.Type.Type, pretForDelete.Montant, "suppression");
                    Utilisateur.calculMontant(pretForDelete.Type.Type, pretForDelete.Montant, "suppression");
                }
                else
                {
                    Contact.calculObjet(pretForDelete.Type.Type, "suppression");
                    Utilisateur.calculObjet(pretForDelete.Type.Type, "suppression");
                }
     
                // Suppression du prêt de la "PretsListe" ou "EmpruntsListe" observable collection.
                if (pretForDelete.Type.Type == "Prêt")
                    PretsListe.Remove(pretForDelete);
                else if (pretForDelete.Type.Type == "Emprunt")
                    EmpruntsListe.Remove(pretForDelete);
     
                // Sauvegarde des changements dans la base de données.
                mesEchangesDB.SubmitChanges();
            }
     
            public void ModifierContact(Contact contactModifie)
            {
                // Mise à jour des données présentes en base.
                Contact.Prenom = contactModifie.Prenom;
                Contact.Nom = contactModifie.Nom;
                Contact.Email = contactModifie.Email;
     
                // Sauvegarde des changements dans la base de données.
                mesEchangesDB.SubmitChanges();
            }
     
            #endregion
        }
    }

    Here is the View page for the accueil contact:

    namespace MesEchanges.View
    {
        public partial class AccueilContact : PhoneApplicationPage
        {
            #region Constructeur
     
            public AccueilContact()
            {
                InitializeComponent();
            }
     
            #endregion
     
            private void ListBox_Tap_1(object sender, System.Windows.Input.GestureEventArgs e)
            {
                // Récupération du prêt sélectionné dans la liste, puis enregistrement dans l'isolated storage pour le retrouver ensuite
                Pret pret = (Pret)pretsListBox.SelectedItem;
                IsolatedStorageSettings.ApplicationSettings["pretId"] = pret.PretId;
     
                // Navigation vers la page d'accueil du prêt
                NavigationService.Navigate(new Uri("/View/AccueilPret.xaml", UriKind.Relative));
            }
     
            private void newPretAppBarButton_Click(object sender, EventArgs e)
            {
                NavigationService.Navigate(new Uri("/View/NewPretPage.xaml", UriKind.Relative));
            }
     
     
            private void deletePretButton_Click(object sender, RoutedEventArgs e)
            {
                MessageBoxResult resultat = MessageBox.Show("Voulez-vous réellement supprimer le prêt/emprunt?", "Suppression Prêt/Emprunt", MessageBoxButton.OKCancel);
     
                if (resultat == MessageBoxResult.OK)
                {
                    // Cast the parameter as a button.
                    var button = sender as Button;
     
                    if (button != null)
                    {
                        // Get a handle for the to-do item bound to the button.
                        Pret pretForDelete = button.DataContext as Pret;
     
                        App.AccueilContactViewModel.DeletePret(pretForDelete);
                    }
     
                    // Put the focus back to the main page.
                    this.Focus();
                }
            }
     
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                // On réinitialise le dataContexte du viewmodel accueil utilisateur ains que celui de l'accueil prêt.
                App.AccueilUtilisateurViewModel = null;
                App.AccueilPretViewModel = null;
     
                // On vérifie si le viewmodel a déjà été instancié (à la première arrivée sur la page) sinon on le fait.
                if (App.AccueilContactViewModel == null)
                {
                    App.AccueilContactViewModel = new AccueilContactViewModel(App.DBConnectionString);
                    App.AccueilContactViewModel.LoadCollectionsFromDatabase();
                    //}
     
                    // Set the page DataContext property to the ViewModel.
                    this.DataContext = App.AccueilContactViewModel;
                }
     
                base.OnNavigatedTo(e);
            }
     
            protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
            {
                // Sauvegarde des changements dans la base de données.
                App.AccueilContactViewModel.SaveChangesToDB();
            }
     
            private void ListBox_Tap_2(object sender, System.Windows.Input.GestureEventArgs e)
            {
                // Récupération de l'emprunt sélectionné dans la liste, puis enregistrement dans l'isolated storage pour le retrouver ensuite
                Pret emprunt = (Pret)empruntsListBox.SelectedItem;
                IsolatedStorageSettings.ApplicationSettings["pretId"] = emprunt.PretId;
     
                // Navigation vers la page d'accueil du prêt
                NavigationService.Navigate(new Uri("/View/AccueilPret.xaml", UriKind.Relative));
            }
     
            private void modifierContactAppBarButton_Click(object sender, EventArgs e)
            {
                NavigationService.Navigate(new Uri("/View/ModifierContactPage.xaml", UriKind.Relative));
            }
        }
    }

    The page to add a prêt:

    namespace MesEchanges.View
    {
        public partial class NewPretPage : PhoneApplicationPage
        {
            private bool ajout = true;
     
            public NewPretPage()
            {
                InitializeComponent();
     
                this.DataContext = App.AccueilContactViewModel;
            }
     
            private void appBarOkButton_Click(object sender, EventArgs e)
            {
                // Récupération de la catégorie
                Categories categorie = (Categories)categoriesListPicker.SelectedItem;
                Types type = (Types)typesListPicker.SelectedItem;
     
                // Vérification que l'utilisateur a renseigné tous les champs.
                if (newPretLibelleTextBox.Text.Length > 0)
                {
                    // S'il s'agit d'un prêt d'argent on s'assure que le montant est renseigné
                    if (categorie.Categorie == "Argent" && newPretMontantTextBox.Text.Length > 0)
                    {
                        // Création d'un nouveau prêt.
                        Pret newPret = new Pret
                        {
                            Libelle = newPretLibelleTextBox.Text,
                            Montant = int.Parse(newPretMontantTextBox.Text),
                            Details = newPretDetailsTextBox.Text,
     
                            // Récupération du type et de la catégorie
                            Type = type,
                            Categorie = categorie,
     
                            // Lien avec le contact
                            Contact = (Contact)IsolatedStorageSettings.ApplicationSettings["contact"],
     
                            // Ces données sont initialisées sans intervention utilisateur
                            DateCreation = DateTime.Now,
                            DateModification = DateTime.Now
                        };
     
                        // Ajouter le prêt au AccueilContactViewModel.
                        App.AccueilContactViewModel.AddPret(newPret);
     
                        // Retour à la page principale.
                        if (NavigationService.CanGoBack)
                        {
                            NavigationService.GoBack();
                        }
                    }
                    else if (categorie.Categorie != "Argent")
                    {
                        // Création d'un nouveau prêt.
                        Pret newPret = new Pret
                        {
                            Libelle = newPretLibelleTextBox.Text,
                            Details = newPretDetailsTextBox.Text,
     
                            // Récupération du type et de la catégorie
                            Type = (Types)typesListPicker.SelectedItem,
                            Categorie = categorie,
     
                            // Lien avec le contact
                            Contact = (Contact)IsolatedStorageSettings.ApplicationSettings["contact"],
     
                            // Ces données sont initialisées sans intervention utilisateur
                            DateCreation = DateTime.Now,
                            DateModification = DateTime.Now
                        };
     
                        // Ajouter le prêt au AccueilContactViewModel.
                        App.AccueilContactViewModel.AddPret(newPret);
     
                        // Retour à la page principale.
                        if (NavigationService.CanGoBack)
                        {
                            NavigationService.GoBack();
                        }
                    }
                }
            }
     
            private void appBarCancelButton_Click(object sender, EventArgs e)
            {
                // Retour à la page principale.
                if (NavigationService.CanGoBack)
                {
                    NavigationService.GoBack();
                }
            }
     
            private void categoriesListPicker_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
            {
                Categories categorie = (Categories)categoriesListPicker.SelectedItem;
     
                if (categorie.Categorie != "Argent")
                {
                    newPretMontantTextBlock.Visibility = System.Windows.Visibility.Collapsed;
                    newPretMontantTextBox.Visibility = System.Windows.Visibility.Collapsed;
                }
                else
                {
                    newPretMontantTextBlock.Visibility = System.Windows.Visibility.Visible;
                    newPretMontantTextBox.Visibility = System.Windows.Visibility.Visible;
                }
            }
        }
    }

    The Utilisateur, Contact et Prêt entities

    namespace MesEchanges.Model
    {
        [Table]
        public class Utilisateur : ViewModelBase, INotifyPropertyChanged, INotifyPropertyChanging
        {
            #region Constructeur
     
            // Assign handlers for the add and remove operations, respectively.
            public Utilisateur()
            {
                _contact = new EntitySet<Contact>(
                    new Action<Contact>(this.attach_Contact),
                    new Action<Contact>(this.detach_Contact)
                    );
            }
     
            #endregion
             
            #region Données
     
            // Define ID: private field, public property, and database column.
            private int _utilisateurId;
     
            [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
            public int UtilisateurId
            {
                get { return _utilisateurId; }
                set { NotifyPropertyChanged(ref _utilisateurId, value); }
            }
     
            // Define item name: private field, public property, and database column.
            private int _montantPrete;
     
            [Column]
            public int MontantPrete
            {
                get { return _montantPrete; }
                set { NotifyPropertyChanged(ref _montantPrete, value); }
            }
     
            // Define completion value: private field, public property, and database column.
            private int _montantEmprunte;
     
            [Column]
            public int MontantEmprunte
            {
                get { return _montantEmprunte; }
                set { NotifyPropertyChanged(ref _montantEmprunte, value); }
            }
     
            private int _objetsPretes;
     
            [Column]
            public int ObjetsPretes
            {
                get { return _objetsPretes; }
                set { NotifyPropertyChanged(ref _objetsPretes, value); }
            }
     
            // Define completion value: private field, public property, and database column.
            private int _objetsEmpruntes;
     
            [Column]
            public int ObjetsEmpruntes
            {
                get { return _objetsEmpruntes; }
                set { NotifyPropertyChanged(ref _objetsEmpruntes, value); }
            }
     
            // Version column aids update performance.
            [Column(IsVersion = true)]
            private Binary _version;
     
            #endregion
     
            #region Mise en place de la fonction NotifyPropertyChanged<T>
     
            private bool NotifyPropertyChanged<T>(ref T variable, T valeur, [CallerMemberName] string nomPropriete = null)
            {
                if (object.Equals(variable, valeur)) return false;
     
                NotifyPropertyChanging(nomPropriete);
                variable = valeur;
                RaisePropertyChanged(nomPropriete);
                return true;
            }
     
            #endregion
     
            #region INotifyPropertyChanging Members
     
            public event PropertyChangingEventHandler PropertyChanging;
     
            // Used to notify that a property is about to change
            private void NotifyPropertyChanging(string propertyName)
            {
                if (PropertyChanging != null)
                {
                    PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
                }
            }
     
            #endregion
     
            #region Relation avec les contacts
     
            // Define the entity set for the collection side of the relationship.
            private EntitySet<Contact> _contact;
     
            [Association(Storage = "_contact", OtherKey = "_fkutilisateurId", ThisKey = "UtilisateurId")]
            public EntitySet<Contact> Contact
            {
                get { return this._contact; }
                set { this._contact.Assign(value); }
            }
     
            #endregion
     
            #region Functions
     
            // Called during an add operation
            private void attach_Contact(Contact contact)
            {
                NotifyPropertyChanging("Contact");
                contact.Utilisateur = this;
            }
     
            // Called during a remove operation
            private void detach_Contact(Contact contact)
            {
                NotifyPropertyChanging("Contact");
                contact.Utilisateur = null;
            }
     
            public void calculMontant(string typePret, int montant, string action)
            {
                if (action == "ajout")
                {
                    if (typePret == "Prêt")
                    {
                        MontantPrete += montant;
                    }
                    else if (typePret == "Emprunt")
                    {
                        MontantEmprunte += montant;
                    }
                }
                else if (action == "suppression")
                {
                    if (typePret == "Prêt")
                    {
                        MontantPrete -= montant;
                    }
                    else if (typePret == "Emprunt")
                    {
                        MontantEmprunte -= montant;
                    }
                }
            }
     
            public void calculObjet(string typePret, string action)
            {
                if (action == "ajout")
                {
                    if (typePret == "Prêt")
                    {
                        ObjetsPretes++;
                    }
                    else if (typePret == "Emprunt")
                    {
                        ObjetsEmpruntes++;
                    }
                }
                else if (action == "suppression")
                {
                    if (typePret == "Prêt")
                    {
                        ObjetsPretes--;
                    }
                    else if (typePret == "Emprunt")
                    {
                        ObjetsEmpruntes--;
                    }
                }
            }
     
            #endregion
        }
    }
    namespace MesEchanges.Model
    {
        [Table]
        public class Contact : ViewModelBase, INotifyPropertyChanged, INotifyPropertyChanging
        {
     
            #region Constructeur
     
            // Assign handlers for the add and remove operations, respectively.
            public Contact()
            {
                _pret = new EntitySet<Pret>(
                    new Action<Pret>(this.attach_Pret),
                    new Action<Pret>(this.detach_Pret)
                    );
            }
     
            #endregion
             
            #region Données
     
            // Define ID: private field, public property, and database column.
            private int _contactId;
     
            [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
            public int ContactId
            {
                get { return _contactId; }
                set { NotifyPropertyChanged(ref _contactId, value); }
            }
     
            private string _prenom;
     
            [Column]
            public string Prenom
            {
                get { return _prenom; }
                set { NotifyPropertyChanged(ref _prenom, value); }
            }
     
            private string _nom;
     
            [Column]
            public string Nom
            {
                get { return _nom; }
                set { NotifyPropertyChanged(ref _nom, value); }
            }
     
            private string _email;
     
            [Column(CanBeNull = true)]
            public string Email
            {
                get { return _email; }
                set { NotifyPropertyChanged(ref _email, value); }
            }
     
            private int _montantPrete;
     
            [Column]
            public int MontantPrete
            {
                get { return _montantPrete; }
                set { NotifyPropertyChanged(ref _montantPrete, value); }
            }
     
            private int _montantEmprunte;
     
            [Column]
            public int MontantEmprunte
            {
                get { return _montantEmprunte; }
                set { NotifyPropertyChanged(ref _montantEmprunte, value); }
            }
     
            private int _objetsPretes;
     
            [Column]
            public int ObjetsPretes
            {
                get { return _objetsPretes; }
                set { NotifyPropertyChanged(ref _objetsPretes, value); }
            }
     
            // Define completion value: private field, public property, and database column.
            private int _objetsEmpruntes;
     
            [Column]
            public int ObjetsEmpruntes
            {
                get { return _objetsEmpruntes; }
                set { NotifyPropertyChanged(ref _objetsEmpruntes, value); }
            }
     
            [Column]
            internal int _fkutilisateurId;
     
            // Version column aids update performance.
            [Column(IsVersion = true)]
            private Binary _version;
     
            #endregion
     
            #region Mise en place de la fonction NotifyPropertyChanged<T>
     
            private bool NotifyPropertyChanged<T>(ref T variable, T valeur, [CallerMemberName] string nomPropriete = null)
            {
                if (object.Equals(variable, valeur)) return false;
     
                NotifyPropertyChanging(nomPropriete);
                variable = valeur;
                RaisePropertyChanged(nomPropriete);
                return true;
            }
     
            #endregion
     
            #region INotifyPropertyChanging Members
     
            public event PropertyChangingEventHandler PropertyChanging;
     
            // Used to notify that a property is about to change
            private void NotifyPropertyChanging(string propertyName)
            {
                if (PropertyChanging != null)
                {
                    PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
                }
            }
     
            #endregion
     
            #region Relation avec l'utilisateur
     
            // Entity reference, to identify the ToDoCategory "storage" table
            private EntityRef<Utilisateur> _utilisateur;
     
            // Association, to describe the relationship between this key and that "storage" table
            [Association(Storage = "_utilisateur", ThisKey = "_fkutilisateurId", OtherKey = "UtilisateurId", IsForeignKey = true)]
            public Utilisateur Utilisateur
            {
                get { return _utilisateur.Entity; }
                set
                {
                    NotifyPropertyChanging("Utilisateur");
                    _utilisateur.Entity = value;
     
                    if (value != null)
                    {
                        _fkutilisateurId = value.UtilisateurId;
                    }
     
                    NotifyPropertyChanging("Utilisateur");
                }
            }
     
            #endregion
     
            #region Relation avec les prêts
     
            // Entity reference, to identify the Pret "storage" table
            private EntitySet<Pret> _pret;
     
            // Association, to describe the relationship between this key and that "storage" table
            [Association(Storage = "_pret", OtherKey = "_fkcontactId", ThisKey = "ContactId")]
            public EntitySet<Pret> Pret
            {
                get { return this._pret; }
                set { this._pret.Assign(value); }
            }
     
            #endregion
     
            #region Functions
     
            // Called during an add operation
            private void attach_Pret(Pret pret)
            {
                NotifyPropertyChanging("Pret");
                pret.Contact = this;
            }
     
            // Called during a remove operation
            private void detach_Pret(Pret pret)
            {
                NotifyPropertyChanging("Pret");
                pret.Contact = null;
            }
     
            public void calculMontant(string typePret, int montant, string action)
            {
                if(action == "ajout")
                {
                    if (typePret == "Prêt")
                    {
                        MontantPrete += montant;
                    }
                    else if(typePret == "Emprunt")
                    {
                        MontantEmprunte += montant;
                    }
                }
                else if (action == "suppression")
                {
                    if (typePret == "Prêt")
                    {
                        MontantPrete -= montant;
                    }
                    else if (typePret == "Emprunt")
                    {
                        MontantEmprunte -= montant;
                    }
                }
            }
     
            public void calculObjet(string typePret, string action)
            {
                if (action == "ajout")
                {
                    if (typePret == "Prêt")
                    {
                        ObjetsPretes++;
                    }
                    else if (typePret == "Emprunt")
                    {
                        ObjetsEmpruntes++;
                    }
                }
                else if (action == "suppression")
                {
                    if (typePret == "Prêt")
                    {
                        ObjetsPretes--;
                    }
                    else if (typePret == "Emprunt")
                    {
                        ObjetsEmpruntes--;
                    }
                }
            }
     
            #endregion
        }
    }
    namespace MesEchanges.Model
    {
        [Table]
        public class Pret : ViewModelBase, INotifyPropertyChanged, INotifyPropertyChanging
        {
            #region Données
     
            // Define ID: private field, public property, and database column.
            private int _pretId;
     
            [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
            public int PretId
            {
                get { return _pretId; }
                set { NotifyPropertyChanged(ref _pretId, value); }
            }
     
            private string _libelle;
     
            [Column]
            public string Libelle
            {
                get { return _libelle; }
                set { NotifyPropertyChanged(ref _libelle, value); }
            }
     
            private int _montant;
     
            [Column(CanBeNull = true)]
            public int Montant
            {
                get { return _montant; }
                set { NotifyPropertyChanged(ref _montant, value); }
            }
     
            private DateTime _dateCreation;
     
            [Column]
            public DateTime DateCreation
            {
                get { return _dateCreation; }
                set { NotifyPropertyChanged(ref _dateCreation, value); }
            }
     
            private DateTime _dateModification;
     
            [Column]
            public DateTime DateModification
            {
                get { return _dateModification; }
                set { NotifyPropertyChanged(ref _dateModification, value); }
            }
     
            private string _details;
     
            [Column(CanBeNull = true)]
            public string Details
            {
                get { return _details; }
                set { NotifyPropertyChanged(ref _details, value); }
            }
     
            [Column]
            internal int _fkcontactId;
     
            [Column]
            internal int _fkcategorieId;
     
            [Column]
            internal int _fktypeId;
     
            // Version column aids update performance.
            [Column(IsVersion = true)]
            private Binary _version;
     
            #endregion
     
            #region Mise en place de la fonction NotifyPropertyChanged<T>
     
            private bool NotifyPropertyChanged<T>(ref T variable, T valeur, [CallerMemberName] string nomPropriete = null)
            {
                if (object.Equals(variable, valeur)) return false;
     
                NotifyPropertyChanging(nomPropriete);
                variable = valeur;
                RaisePropertyChanged(nomPropriete);
                return true;
            }
     
            #endregion
     
            #region INotifyPropertyChanging Members
     
            public event PropertyChangingEventHandler PropertyChanging;
     
            // Used to notify that a property is about to change
            private void NotifyPropertyChanging(string propertyName)
            {
                if (PropertyChanging != null)
                {
                    PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
                }
            }
     
            #endregion
     
            #region Relation avec le Contact
     
            // Entity reference, to identify the ToDoCategory "storage" table
            private EntityRef<Contact> _contact;
     
            // Association, to describe the relationship between this key and that "storage" table
            [Association(Storage = "_contact", ThisKey = "_fkcontactId", OtherKey = "ContactId", IsForeignKey = true)]
            public Contact Contact
            {
                get { return _contact.Entity; }
                set
                {
                    NotifyPropertyChanging("Contact");
                    _contact.Entity = value;
     
                    if (value != null)
                    {
                        _fkcontactId = value.ContactId;
                    }
     
                    NotifyPropertyChanging("Contact");
                }
            }
     
            #endregion
     
            #region Relation avec les Categories
     
            // Entity reference, to identify the ToDoCategory "storage" table
            private EntityRef<Categories> _categorie;
     
            // Association, to describe the relationship between this key and that "storage" table
            [Association(Storage = "_categorie", ThisKey = "_fkcategorieId", OtherKey = "CategorieId", IsForeignKey = true)]
            public Categories Categorie
            {
                get { return _categorie.Entity; }
                set
                {
                    NotifyPropertyChanging("Categorie");
                    _categorie.Entity = value;
     
                    if (value != null)
                    {
                        _fkcategorieId = value.CategorieId;
                    }
     
                    NotifyPropertyChanging("Categorie");
                }
            }
     
            #endregion
     
            #region Relation avec les Types
     
            // Entity reference, to identify the ToDoCategory "storage" table
            private EntityRef<Types> _type;
     
            // Association, to describe the relationship between this key and that "storage" table
            [Association(Storage = "_type", ThisKey = "_fktypeId", OtherKey = "TypeId", IsForeignKey = true)]
            public Types Type
            {
                get { return _type.Entity; }
                set
                {
                    NotifyPropertyChanging("Type");
                    _type.Entity = value;
     
                    if (value != null)
                    {
                        _fktypeId = value.TypeId;
                    }
     
                    NotifyPropertyChanging("Type");
                }
            }
     
            #endregion
        }
    }

    And here is the DataContext with the database connection :

    namespace MesEchanges.Model
    {
        #region DataContext
     
        public class MesEchangesDataContext : DataContext
        {
            // Pass the connection string to the base class.
            public MesEchangesDataContext(string connectionString)
                : base(connectionString)
            { }
     
            // Specify a table for the Utilsateur utilisateurs.
            public Table<Utilisateur> Utilisateur;
     
            // Specify a table for the contact.
            public Table<Contact> Contact;
     
            // Specify a table for the prêt.
            public Table<Pret> Pret;
     
            // Specify a table for the catégorie.
            public Table<Categories> Categorie;
     
            // Specify a table for the type.
            public Table<Types> Type;
        }
     
        #endregion
    }
    Don't hesitate if you need further details.
    Alexandre

    A.Vescera

    Tuesday, October 22, 2013 10:08 AM

All replies

  • Hello,

    It seems that if we set an object of the entity and remove the new record before any submit Linq still thinks we want to add the new record. In this case we have to set all objects that have FK references to null.

    So I guess if it is that there is a table which has a relationship with Pret and the relationship is Pret: table => 0:N.

    If it is, please see this post which describes the problem and solution in detail:

    http://social.msdn.microsoft.com/Forums/en/linqtosql/thread/4170c7bb-f727-4e6a-9190-fc268ae4ce4b

    Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, October 23, 2013 1:54 AM
  • Hi Fred Bao,

    Thanks for your answer, but this not seems to be my problem.

    In fact, I effectively delete an item 'Prêt', but the encountered error is linked to my 'Contact' item.

    I performed some more tests yesterday and here is what I noticed:

    The error occures when I try to update some fields of my 'Contact' parent entity (remember that I have 'Contacts' linked to 0:N 'Prêt' entities).

    So here is the code where I have to work on:

    // Suppression d'un prêt de la base de données et de la collection.
            public void DeletePret(Pret pretForDelete)
            {
                // Suppression du prêt du data context.
                mesEchangesDB.Pret.DeleteOnSubmit(pretForDelete);
                Contact.Pret.Remove(pretForDelete);
     
                if (pretForDelete.Categorie.Categorie == "Argent")
                {
                    Contact.calculMontant(pretForDelete.Type.Type, pretForDelete.Montant, "suppression");
                    Utilisateur.calculMontant(pretForDelete.Type.Type, pretForDelete.Montant, "suppression");
                }
                else
                {
                    Contact.calculObjet(pretForDelete.Type.Type, "suppression");
                    Utilisateur.calculObjet(pretForDelete.Type.Type, "suppression");
                }
     
                // Suppression du prêt de la "PretsListe" ou "EmpruntsListe" observable collection.
                if (pretForDelete.Type.Type == "Prêt")
                    PretsListe.Remove(pretForDelete);
                else if (pretForDelete.Type.Type == "Emprunt")
                    EmpruntsListe.Remove(pretForDelete);
     
                // Sauvegarde des changements dans la base de données.
                mesEchangesDB.SubmitChanges();
            }

    If you want to see the whole AccueilContactViewModel code, please refer upper in this tread, since it's a big part I did not paste here.

    What I found is when I comment tha Contact part, I mean these two lines:

    Contact.calculMontant(pretForDelete.Type.Type, pretForDelete.Montant, "suppression");

    And

    Contact.calculObjet(pretForDelete.Type.Type, "suppression");

    I don't encounter the error anymore.

    So my investigation is that when I try to update my Contact entity, and then try to submit the changes (then after modyfying fields in Contact and also deleting my 'Prêt' entity) I have the error.

    The error is linked with the update of the fields in my Contact entity.

    What I tried to fix the issue, and which did not work.

    I tried to recover the entire entity from the database directly into my delete function (even if normally I could use the one from the DataContext) -> did not work.

    Try to recover the Prêt entity linked to the button, by recovering it from the DB (even if normally I could use the prêt from the Button.DataContext) -> did not work.

    I don't know what's wrong with my Contact entity, because even when watching (in debug mode) the data of this entity, the _fkutilisateurId (that seems to cause my issue) is always filled correctly (at least it seems to be filled correctly :) ).

    Regards,


    A.Vescera

    Wednesday, October 23, 2013 7:26 AM
  • Hi,

    So I find a workaround to this problem, and that is a correct one (not a bad hotfix that just makes the app working).

    However, this workaround does not explain why I had this issue, and so I still not know the reason of the problem.

    To fix this, I externalized the update code into a dedicated method, that take as a parameter the 'Pret' entity (to use its data) and once done, I do a SubmitChanges(); that makes my 'contact' and 'Utilisateur' entity data to be updated into my DB.

    Only after this action I proceed to the deletion of my 'Pret' entity, and there it's correctly working (so I delete the 'Pret' entity and finish with another SubmitChanges(); this one just perform the correct deletion into the database).


    A.Vescera

    • Marked as answer by A.Vescera Thursday, October 24, 2013 7:53 AM
    • Unmarked as answer by A.Vescera Thursday, October 24, 2013 8:32 PM
    Thursday, October 24, 2013 7:53 AM
  • I open again my issue, because it's still there.

    Don't know why it has worked yesterday.


    A.Vescera

    Thursday, October 24, 2013 8:40 PM
  • It is recommended to share the program to skydive so that we can download it and test it.

    Thanks&Regards.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, October 30, 2013 3:18 AM