2013-05-24 9 views
8

Mam problem z Entity Framework 4.0. Próbuję zapisać obiekt "Treatment", który ma kolekcję obiektów "Segment". Ilekroć próbuję dodawać/edytować obiekt Treatment gdzie dodaję 2 lub więcej nowych segmentów, pojawia się następujący błąd:Błąd z Entity Framework: AcceptChanges nie może być kontynuowany, ponieważ wartości kluczy obiektu kolidują z innym obiektem w ObjectStateManager

The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.

Oto sposób zaoszczędzić używam. Kolumna "SegmentID" to PK dla "Segmentu" i jest to liczba całkowita, która jest ustawiona na auto inkrement w DB (MS SQL 2008). Domyślnie "Identyfikator segmentu" jest ustawiony na 0, dopóki nie otrzyma zaktualizowanego segmentu z bazy danych.

public bool Save(Treatment myTreatment) 
    { 
     bool result = false; 


     using (tamcEntities db = new tamcEntities()) 
     { 
      // IF NEW TREATMENT, CREATE IT AND ADD TO DB 
      if (myTreatment.Treatment_ID == 0) 
      { 

       db.Treatments.AddObject(myTreatment); 
       result = (db.SaveChanges() != 0); 

      } 
      // IF EXISTING TREATMENT, FIND EXISTING TREATMENT IN DB, AND UPDATE IT 
      else 
      { 
       List<string> treatmentIncludes = new List<string>(); 
       treatmentIncludes.Add("Segments"); 

       Treatment myTmt = (from x in db.Treatments 
            where x.Treatment_ID == myTreatment.Treatment_ID 
            select x).WithIncludes(treatmentIncludes).FirstOrDefault(); 

       if (myTmt != null) 
       { 

        myTmt.Comment = myTreatment.Comment; 
        myTmt.Cost = myTreatment.Cost; 
        myTmt.CostItemDrain = myTreatment.CostItemDrain; 
        myTmt.CostItemE2E = myTreatment.CostItemE2E; 
        myTmt.CostItemEnhan = myTreatment.CostItemEnhan; 
        myTmt.CostItemEnv = myTreatment.CostItemEnv; 
        myTmt.CostItemGuard = myTreatment.CostItemGuard; 
        myTmt.CostItemOther = myTreatment.CostItemOther; 
        myTmt.CostItemPed = myTreatment.CostItemPed; 
        myTmt.CostItemSub = myTreatment.CostItemSub; 
        myTmt.CostItemTraffic = myTreatment.CostItemTraffic; 
        myTmt.CostItemUtl = myTreatment.CostItemUtl; 
        myTmt.Create_DateTime = myTreatment.Create_DateTime; 
        myTmt.Create_Entity = myTreatment.Create_Entity; 
        myTmt.Create_User = myTreatment.Create_User; 
        myTmt.Description = myTreatment.Description; 
        myTmt.Improvement_Type = myTreatment.Improvement_Type; 
        myTmt.Jurisdiction = myTreatment.Jurisdiction; 
        myTmt.Last_Update_DateTime = myTreatment.Last_Update_DateTime; 
        myTmt.Last_Update_Entity = myTreatment.Last_Update_Entity; 
        myTmt.Last_Update_User = myTreatment.Last_Update_User; 
        myTmt.Life_Expectancy = myTreatment.Life_Expectancy; 
        myTmt.MDOTJobID = myTreatment.MDOTJobID; 
        myTmt.Planned = myTreatment.Planned; 
        myTmt.Project_Classification = myTreatment.Project_Classification; 
        myTmt.ProjectID = myTreatment.ProjectID; 
        myTmt.Quantity = myTreatment.Quantity; 
        myTmt.SurfaceTypeAfter = myTreatment.SurfaceTypeAfter; 
        myTmt.tmp_treat = myTreatment.tmp_treat; 
        myTmt.Treatment_Date = myTreatment.Treatment_Date; 
        myTmt.Unit_of_Measure = myTreatment.Unit_of_Measure; 



        // DELETE MISSING SEGMENTS THAT ARE NO LONGER PART OF THE TREATMENT 
        List<int> segmentIDsToKeep = myTreatment.Segments.Select(x => x.SegmentID).ToList(); 
        myTmt.Segments.Where(x => !segmentIDsToKeep.Contains(x.SegmentID)).ToList().ForEach(x => db.Segments.DeleteObject(x)); 


        // ITERATE OVER EACH SEGMENT AND INSERT OR UPDATE IT 
        foreach (Segment s in myTreatment.Segments) 
        { 

         if (!string.IsNullOrWhiteSpace(s.PR) && !string.IsNullOrWhiteSpace(s.BMP.ToString()) && !string.IsNullOrWhiteSpace(s.EMP.ToString())) 
         { 
          Segment mySegment = new Segment(); 

          // IF EXISTING SEGMENT, FIND EXISTING SEGMENT IN DB, AND UPDATE IT 
          if (s.SegmentID != 0) 
          { 
           mySegment = (from x in myTmt.Segments 
              where x.SegmentID == s.SegmentID 
              select x).FirstOrDefault(); 
          } 

          mySegment.ActualLength = s.ActualLength; 
          mySegment.BMP = s.BMP; 
          mySegment.Create_DateTime = s.Create_DateTime; 
          mySegment.Create_Entity = s.Create_Entity; 
          mySegment.Create_User = s.Create_User; 
          mySegment.EMP = s.EMP; 
          mySegment.HasRequiredHPMS = s.HasRequiredHPMS; 
          mySegment.Lanes = s.Lanes; 
          mySegment.Last_Update_DateTime = s.Last_Update_DateTime; 
          mySegment.Last_Update_Entity = s.Last_Update_Entity; 
          mySegment.Last_Update_User = s.Last_Update_User; 
          mySegment.PASER_Rating = s.PASER_Rating; 
          mySegment.PR = s.PR; 
          mySegment.RoadName = s.RoadName; 
          mySegment.SurfaceType = s.SurfaceType; 
          mySegment.Treatment_ID = s.Treatment_ID; 
          mySegment.Version = s.Version; 

          // If the BMP is greater than the EMP, swap them. 
          if (mySegment.BMP > mySegment.EMP) 
          { 
           decimal tempBMP = mySegment.BMP; 
           decimal tempEMP = mySegment.EMP; 

           mySegment.BMP = tempEMP; 
           mySegment.EMP = tempBMP; 
          } 


          // IF NEW SEGMENT, ADD IT 
          if (s.SegmentID == 0) 
          { 
           myTmt.Segments.Add(mySegment); 
          } 



         } 

        } 

        result = (db.SaveChanges(SaveOptions.AcceptAllChangesAfterSave) != 0); 
       } 

      } 



     } 

     return result; 
    } 

Odpowiedz

2

Zagadnienie to jesteś przypisując ten sam Segment klawisz dwa razy w swoim kontekście, który Mucks górę ObjectStateManager.

myTreatment ma kolekcję jednostek Segment, z których wszystkie są śledzone. Teraz, jak pętla przez nich utworzyć inny Segment, które mogłyby skończyć się o ten sam klucz jak istniejący Segment w swojej kolekcji:

foreach (Segment s in myTreatment.Segments){ 
    .... 
    Segment mySegment = new Segment(); //NEW OBJECT 

    if (s.SegmentID != 0) 
    { 
     //IN HERE YOU ASSIGN THE SAME KEY TO THE NEW OBJECT 
     //s.SegmentID == mySegment.SegmentID **CONFLICT** 
     mySegment = (from x in myTmt.Segments 
        where x.SegmentID == s.SegmentID 
        select x).FirstOrDefault(); 
    }   
0

Błąd pokazuje jeśli przypisać kolumnę jako wyjątkowy i spróbuj zapisać sam wartość do tej kolumny. Mogę podać ci wskazówkę, czy jest to wykonalne dla ciebie. Aby to działało, można dodać nowe auto zwiększane kolumnę o nazwie „id” w tablicy segmentów i traktują tę kolumnę jako kluczowy

table: segment 
id- new auto incremented key column 
treatment_id 
segment_id 

entity: 
id- key 
treatment_id 
segment_id 

teraz wykonać operację dodawania. Wykonaj operację edycji i usunięcia encji segmentu na podstawie identyfikatora segmentu.

2

Mam taki sam błąd podczas wstawiania wierszy do tabeli Oracle, rozwiązano edmx edycję pliku jako xml (prawy przycisk myszy, otwórz za pomocą .., edytor XML) i dodano StoreGeneratedPattern="Identity" do definicji tabeli.

Przed

<Property Name="ID" Type="number" Nullable="false" Precision="38" Scale="0" /> 

Po

<Property Name="ID" Type="number" Nullable="false" Precision="38" Scale="0" StoreGeneratedPattern="Identity" /> 
+0

to pracował dla mnie. –

Powiązane problemy