locked
Update an Entity Relations with an *-* FK RRS feed

  • Question

  • Hi everybody,

    i have an entity "Shareholder" that has *-* relation with "FamilySpecs"

    i retrieve a Shareholder entity from my Context and load its FamilySpecs with this Method in [ShareholderModel] class

     public static Shareholder GetByShareholderID(string shID)
    
    
    
     {
    
    
    
      using (NYSStockEntities ent = new NYSStockEntities())
    
    
    
      {
    
    
    
      Shareholder sh = ent.Shareholders.SingleOrDefault(s => s.ShareholderID == shID);
    
    
    
      sh.FamilySpecs.Load();
    
    
    
      return sh;
    
    
    
      }
    
    
    
     }
    
    
    
    

    in my Form i have a DataGridView that shows all FamilySpecs and Checked ones that contains in Shareholder with this method:

     public static List<FamilySpec> GetShareholderFamilySpecsCheckList(Shareholder shareHolder)
    
    
    
     {
    
    
    
      var q = (from fs in FamilySpecModel.GetList()
    
    
    
       select new FamilySpec
    
    
    
       {
    
    
    
        ID = fs.ID,
    
    
    
        Title = fs.Title,
    
    
    
        Checked = (shareHolder.FamilySpecs.SingleOrDefault(f => f.ID == fs.ID) != null ? true : false)
    
    
    
       });
    
    
    
      return q.ToList<FamilySpec>();
    
    
    
     }
    
    
    
    

    and bind it to that DataGridView with this method:

      dgvFamilySpec.DataSource = FamilySpecModel.GetShareholderFamilySpecsCheckList(shareHolder);
    
    
    
    
    
    
    
    

    when the user wants to Save the Shareholder, i use this method in my form to update FamilySpecs of my Shareholder class depends on DataGridview datas:

     public static void UpdateFamilySpecs(Shareholder shareHolder, List<FamilySpec> familySpecs)
    
    
    
     {
    
    
    
      foreach (FamilySpec fs in familySpecs)
    
    
    
      {
    
    
    
      FamilySpec f = shareHolder.FamilySpecs.SingleOrDefault(s => s.ID == fs.ID);
    
    
    
      if (f != null)
    
    
    
      {
    
    
    
       if (fs.Checked == false)
    
    
    
       {
    
    
    
       shareHolder.FamilySpecs.Remove(fs);
    
    
    
       }
    
    
    
      }
    
    
    
      else
    
    
    
      {
    
    
    
       if (fs.Checked == true)
    
    
    
       {
    
    
    
       using (NYSStockEntities ent= new NYSStockEntities())
    
    
    
       {
    
    
    
        FamilySpec familySpec = ent.FamilySpecs.SingleOrDefault(f1 => f1.ID == fs.ID);
    
    
    
        ent.Detach(familySpec);
    
    
    
        shareHolder.FamilySpecs.Add(familySpec);
    
    
    
       }
    
    
    
       }
    
    
    
      }
    
    
    
      }
    
    
    
     }
    
    
    
    
    
    
    
    

    but it show me this errors:

    {"Violation of PRIMARY KEY constraint 'PK_FamilySpec'. Cannot insert duplicate key in object 'dbo.FamilySpec'.\r\nThe statement has been terminated."}

    what should i do?

    Thanks 


    Amin Mashayekhi
    Tuesday, May 11, 2010 6:53 AM

Answers

  • These two lines are probably not doing what you think they are doing:

        ent.Detach(familySpec);
        shareHolder.FamilySpecs.Add(familySpec);

    The Detach call tells the EF that the familySpec entity should be removed from the context.  This will not have any impact on the store; it's purely an operation on the internal cache.  There are actually very few places where Detach is useful.

    The Add call does two things.  First it adds the familySpec to the collection of specs on the shareholder.  In other words, it creates a relationship between the familySpec and the shareHolder.  Second, because familySpec is not in the context, it adds the familySpec to the context and marks it as Added.  This means that the entity will be INSERTed into the database when you call SaveChanges.

    You can probably now see why you get the exception--the database already has a familySpec with the given ID, but you're now trying to insert a new one with the same ID as well.

    You probably want to try something like:

                                if (!shareHolder.FamilySpecs.Contains(familySpec))
                                {
                                    shareHolder.FamilySpecs.Add(familySpec);
                                }

    This will create a relationship between the two entities if one doesn't already exist but will not try to insert a new famlySpec into the database.

    Hope this helps,

    Arthur

     

    Thursday, May 13, 2010 4:15 PM