Answered Handling Unique ID error

  • Thursday, April 26, 2012 8:35 AM
     
      Has Code

    Hi everyone

    I have the following issue. I have an ID field that needs to be put in manually and that needs to be unique. It is the primary key in my database so the unique error will fire if I try to insert the same ID. The problem is in the handling of the error. If I do this:

    catch (Exception ex)
                        {
                            
                            transaction.Rollback();
                            MessageBox.Show("Doslo je do greske " + ex.Message);
    
                            
    
                        }
                    }


    It will give me a message box which shows the error but this code

    public void SaveDobavljac(Dobavljac dobavljac)
            {
                if (dobavljac.IsNew== true)
                {
                if (!CurrentDobavljac.Contains(dobavljac))
                    CurrentDobavljac.Add(dobavljac);
    
                _dobavljacRepository.Save(dobavljac);
    
                StatusText = string.Format("Dobavljac '{0}' je spašen.", dobavljac.LookupDobavljac);
                
            }
                else
                {
                    _dobavljacRepository.Update(dobavljac);
                }
            }

    still all goes through, so I still see the dobavljac in my grid.

    On the other hand if I do this

    catch (Exception ex)
                        {
                            
                            transaction.Rollback();
                          
                            throw new Exception("Failed to fill adapter. SQL is: '" + oleComd.CommandText + "' and error is: " + ex.Message); ;
    
                        }
                    }

    It will exit the application and show the error, which is not something I want to happen.

    Ideally the solution would be for the textbox to go red and in the tooltip to show the error which is kinda how it works with the validation I have in place

    but idealism is perhaps too ambitious so I would settle for the message box but the grid not showing the non existing (in the database) row.

    Hopefully one of you guys can help me achieve this.

All Replies

  • Thursday, April 26, 2012 8:46 AM
     
      Has Code

    hi,

    put the

    try
    catch


    in the

    SaveDobavljac

    sub, and switch the save code with the add code:

    public void SaveDobavljac(Dobavljac dobavljac)
    {
       if (dobavljac.IsNew== true)
       {
            if (!CurrentDobavljac.Contains(dobavljac))
    	{
    		try
    		{
    		    _dobavljacRepository.Save(dobavljac);
                        CurrentDobavljac.Add(dobavljac);
    		}
    
    		catch
    		{
    		   ...
    		}
            }
       }
    }

    If the exception occurs, it will not go trough with the add


    Regards, Nico

  • Thursday, April 26, 2012 11:10 AM
     
      Has Code

    Hi Nico, I tried your suggestion but unfortunately I still see the Dobavljac in the grid

     public void SaveDobavljac(Dobavljac dobavljac)
            {
                if (dobavljac.IsNew== true)
                {
                if (!CurrentDobavljac.Contains(dobavljac))
                    try
                    {
                        CurrentDobavljac.Add(dobavljac);
                       
                        _dobavljacRepository.Save(dobavljac);
    
                        StatusText = string.Format("Dobavljac '{0}' je spašen.", dobavljac.LookupDobavljac);
                    }
                    catch
    		{
                
                MessageBox.Show("Doslo je do greske ");
                      
                StatusText = string.Format("Dobavljac '{0}' nije spasen.", dobavljac.LookupDobavljac);
    		}
            }
                else
                {
                    _dobavljacRepository.Update(dobavljac);
                }
            }

    This is the code I tried with. When I debug it just jumps through the if (!CurrentDobavljac.Contains(dobavljac)) like it doesn't contain that dobavljac which I don't get since when I check the collection it has the id number that I am repeating. It's not GUID though, I use a regular INT since I need the user to insert it manually.

    Thanks for your help.

  • Thursday, April 26, 2012 12:18 PM
     
     
    if you look at my code, it does the save first, then the add.

    Regards, Nico

  • Friday, April 27, 2012 7:34 AM
     
      Has Code
    Yeah I tried that as well but that still gives me the same issue.
    public void SaveDobavljac(Dobavljac dobavljac)
            {
                if (dobavljac.IsNew== true)
                {
                if (!CurrentDobavljac.Contains(dobavljac))
                    try
                    {
    
                        _dobavljacRepository.Save(dobavljac);
    
                        CurrentDobavljac.Add(dobavljac);
                       
                        StatusText = string.Format("Dobavljac '{0}' je spašen.", dobavljac.LookupDobavljac);
                    }
                    catch
    		{
                
                MessageBox.Show("Doslo je do greske ");
                      
                StatusText = string.Format("Dobavljac '{0}' nije spasen.", dobavljac.LookupDobavljac);
    		}
            }
                else
                {
                    _dobavljacRepository.Update(dobavljac);
                }
            }
    I run the code and it gives me the error for the Unique Primary key but then It shows me the
    StatusText = string.Format("Dobavljac '{0}' je spašen.", dobavljac.LookupDobavljac);
    Which I don't understand.
  • Tuesday, May 01, 2012 9:51 AM
    Moderator
     
     

    Hi,

    I think the problem can be caused by this line of codes: if (!CurrentDobavljac.Contains(dobavljac))

    What's the data type of CurrentDobavljac?  How can it verify there is no duplicate primary keys of dbavljac objects inside?  If it is just a generic List of dobavljac object, it will use the default method of .NET -- using object reference to check whether two objects are equal instead of their primary key value. 

    Good day!

    Thanks


    Michael Sun [MSFT]
    MSDN Community Support | Feedback to us

  • Thursday, May 03, 2012 6:54 AM
     
      Has Code

    Current Dobavljac is an Observable Collection

    private ObservableCollection<Dobavljac> _currentDobavljac;
    
    _currentDobavljac = new ObservableCollection<Dobavljac>(dobavljacRepository.FindAll());
    
    
    public ObservableCollection<Dobavljac> CurrentDobavljac
            {
                get { return _currentDobavljac; }
                set { _currentDobavljac = value; OnPropertyChanged("CurrentDobavljac"); }
            }

  • Thursday, May 03, 2012 1:15 PM
    Moderator
     
     Answered

    Hi,

    If you want to compare the objects in the ObserableCollection, I believe we need to create a comparer especially for the Dobavljac object.  You can refer to the PersonComparer in this thread, http://forums.silverlight.net/t/50468.aspx

    Good day!

    Thanks


    Michael Sun [MSFT]
    MSDN Community Support | Feedback to us

    • Marked As Answer by dino2dy Thursday, May 10, 2012 7:46 AM
    •  
  • Thursday, May 03, 2012 1:27 PM
     
     
    Thank you Michael I will give that a look.
  • Wednesday, May 09, 2012 10:38 AM
     
      Has Code

    Ok so I tried the comparer. I created a class that compares my Primary keys which are Id's

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Inventar.Model;
    using Inventar.Presenters;
    using Inventar.Views;
    
    namespace Inventar.Presenters
    {
        class IdComparer : IEqualityComparer<Dobavljac>
        {
            
           
                // Products are equal if their Id's are equal.
                public bool Equals(Dobavljac x, Dobavljac y)
                {
    
                    //Check whether the compared objects reference the same data.
                    if (Object.ReferenceEquals(x, y)) return true;
    
                    //Check whether any of the compared objects is null.
                    if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
                        return false;
    
                    //Check whether the products' properties are equal.
                    return x.Dob_Id == y.Dob_Id;
                }
    
                // If Equals() returns true for a pair of objects 
                // then GetHashCode() must return the same value for these objects.
    
                public int GetHashCode(Dobavljac dobavljac)
                {
                    //Check whether the object is null
                    if (Object.ReferenceEquals(dobavljac, null)) return 0;
    
                    
    
                    //Get hash code for the Code field.
                    int hashProductCode = dobavljac.Dob_Id.GetHashCode();
    
                    //Calculate the hash code for the product.
                    return hashProductCode;
                }
    
            }
    
        }
    

    Ok so that should compare the Dob.Id fields of the class Dobavljac, which are the primary keys.

    So then in my insert code I do this:

     public void SaveDobavljac(Dobavljac dobavljac)
            {
                
                if (dobavljac.IsNew== true)
                {
                //if (!CurrentDobavljac.Contains(dobavljac))
    
                    if (dobavljac.Dob_Id.Equals(false))
                    
                      
    
                            
                    try
                    {
    
                        _dobavljacRepository.Save(dobavljac);
    
                        CurrentDobavljac.Add(dobavljac);
                       
                        StatusText = string.Format("Dobavljac '{0}' je spašen.", dobavljac.LookupDobavljac);
                    }

    This always skips everything.

    If I try this

     public void SaveDobavljac(Dobavljac dobavljac)
            {
                bool jednako=dobavljac.Dob_Id.Equals(new IdComparer());
                if (dobavljac.IsNew== true)
                {
                //if (!CurrentDobavljac.Contains(dobavljac))
                    //if (dobavljac.Dob_Id.Equals(false))
                    if (jednako == false) 
                      
    
                            
                    try
                    {
    
                        _dobavljacRepository.Save(dobavljac);
    
                        CurrentDobavljac.Add(dobavljac);
                       
                        StatusText = string.Format("Dobavljac '{0}' je spašen.", dobavljac.LookupDobavljac);
                    }

    This always goes through the code, no matter if the primary key is a duplicate, so jednako is always false.

    I also tried changing the IdComparer like this

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Inventar.Model;
    using Inventar.Presenters;
    using Inventar.Views;
    
    namespace Inventar.Presenters
    {
        class IdComparer : IEqualityComparer<Dobavljac>
        {
            
           
                
                public bool Equals(Dobavljac x, Dobavljac y)
                {
    
                    if (x.Dob_Id == y.Dob_Id)
    
                    {
                        return true;
    
                    }
    
                    else
    
                    {
                        return false;
    
                    }
    
    
    
                    
                }
    
    
                public int GetHashCode(Dobavljac dobavljac)
                {
                    //Check whether the object is null
                    if (Object.ReferenceEquals(dobavljac, null)) return 0;
    
                    
    
                    //Get hash code for the Code field.
                    int hashProductCode = dobavljac.Dob_Id.GetHashCode();
    
                    //Calculate the hash code for the product.
                    return hashProductCode;
                }
    
            }
    
        }
    
    

    No luck. I'm just no sure what I'm doing wrong.

    Please help.


    • Edited by dino2dy Wednesday, May 09, 2012 11:07 AM
    •  
  • Wednesday, May 09, 2012 1:33 PM
    Moderator
     
     Answered Has Code

    Hi,

    I created such a demo for your references:

    public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ObservableCollection<MyObject> colleciton = new ObservableCollection<MyObject>(); MyObject o1 = new MyObject() { ID = 1, Name = "Michael" }; MyObject o2 = new MyObject() { ID = 1, Name = "Michael" }; colleciton.Add(o1); if (colleciton.Contains(o2, new IdComparer())) { MessageBox.Show("Duplicate"); } } } public class MyObject { public int ID { get; set; } public string Name { get; set; } } public class IdComparer : IEqualityComparer<MyObject> { public bool Equals(MyObject x, MyObject y) { if (x.ID == y.ID) { return true; } else { return false; } } public int GetHashCode(MyObject x) { if (x == null) return 0; return x.ID.GetHashCode(); } }

    Or we can override the Equals and GetHashCode method of the Dobavljac object.  Here are some sample codes:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                ObservableCollection<MyObject> colleciton = new ObservableCollection<MyObject>();
                MyObject o1 = new MyObject() { ID = 1, Name = "Michael" };
                MyObject o2 = new MyObject() { ID = 1, Name = "Michael" };
    
                colleciton.Add(o1);
    
                if (colleciton.Contains(o2)
                {
                    MessageBox.Show("Duplicate");
                }
            }
        }
    
        public class MyObject
        {
            public int ID { get; set; }
            public string Name { get; set; }
    
            public override bool Equals(object obj)
            {
                MyObject o = obj as MyObject;
                return ID.Equals(o.ID);
            }
    
            public override int GetHashCode()
            {
                return ID.GetHashCode();
            }
        }

    Good day!

    Thanks


    Michael Sun [MSFT]
    MSDN Community Support | Feedback to us

    • Marked As Answer by dino2dy Thursday, May 10, 2012 7:20 AM
    •  
  • Thursday, May 10, 2012 7:26 AM
     
      Has Code

    Thank you so much Michael it works like a charm.

    if (!CurrentDobavljac.Contains(dobavljac, new IdComparer))

    I didn't know where to initialize the IdComparer, but your demo showed me.

    You have been extremely helpful in this matter and I want to thank you once again for taking the time and having the patience to guide a newbie through this problem.

  • Thursday, May 10, 2012 7:54 AM
     
      Has Code

    If I could bother you for one more thing and I can make a new thread but I figured since it's kinda related to ask you here.

    Is there a way for me to avoid the message box that pops up and instead have the text box just go red and in the tooltip show the error. I had this other validation done this way.

    I have created a Validators class that inherits from ValidationRule. And it fires a false Validation Result when the user tries to write in a non number or a 0.

    namespace Inventar.Presenters
    {
       public class Validators:ValidationRule
        {
          
    
          public override ValidationResult Validate(object value,
                System.Globalization.CultureInfo cultureInfo)
            {
                int IntValue=0;
               
                try
                {
                   IntValue=Convert.ToInt16(value);
                   
                }
                catch (Exception)
                {
                    return new ValidationResult(false, "Molimo upišite broj");
                }
    
                if (IntValue < 0) return new ValidationResult(false, "Molimo upišite broj veći od 0");
    
                //if (!CurrentDobavljac.Contains(dobavljac, new IdComparer()))) return new ValidationResult (false, "Taj Dobavljac vec postoji");
                
                return new ValidationResult(true, null);
    
          }
    
    
        }
    
    }

    Then in the back code for the View I have this Validation Error Event

    private void TextBox_Error(object sender, ValidationErrorEventArgs e)
            {
                if (e.Action == ValidationErrorEventAction.Added)
                {
                    ((Control)sender).ToolTip = e.Error.ErrorContent.ToString();
                }
                else
                {
                    ((Control)sender).ToolTip = "";
                }
            }

    Which tells the text box what to do. And then in the wpf I just add this textbox_error event to the textbox of my choosing.

    So is there a way to somehow implement this error handling for the Comparer as well?

    If this is not possible, your solution works just fine, this is more a bells and whistles kinda thing.

  • Friday, May 11, 2012 1:40 AM
    Moderator
     
     

    Hi,

    You're very welcome!  :)

    For the follow-up question about the validation in WPF, I would recommend you post a new thread in WPF forum here, http://social.msdn.microsoft.com/forums/en-US/wpf/threads/    Honestly, I am not a WPF expert.  But I believe you will get very good support from the experts in WPF forum. 

    Have a nice weekend!

    Thanks


    Michael Sun [MSFT]
    MSDN Community Support | Feedback to us

  • Friday, May 11, 2012 6:45 AM
     
     
    Ok thank you once again Michael, and you have a great weekend as well!!!