2013-05-24 27 views
8

Tôi đang gặp sự cố với Entity Framework 4.0. Tôi đang cố lưu đối tượng "Điều trị" có bộ sưu tập đối tượng "Phân đoạn". Bất cứ khi nào tôi cố gắng thêm/chỉnh sửa đối tượng Điều trị nơi tôi thêm 2 hoặc nhiều Phân đoạn mới, tôi nhận được lỗi sau:Lỗi với khung thực thể: AcceptChanges không thể tiếp tục vì các giá trị khóa của đối tượng xung đột với một đối tượng khác trong 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.

Đây là phương pháp lưu tôi đang sử dụng. Cột "SegmentID" là PK cho "Phân đoạn" và nó là một số nguyên được đặt thành tăng tự động trong DB (MS SQL 2008). Theo mặc định, "SegmentID" được đặt thành 0 cho đến khi nó nhận được phân đoạn được cập nhật từ DB.

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; 
    } 

Trả lời

2

Vấn đề là bạn đang gán cùng một phím Segment hai lần trong ngữ cảnh của bạn, làm hài lòng ObjectStateManager.

myTreatment có một bộ sưu tập gồm Segment pháp nhân, tất cả đều được theo dõi. Bây giờ, khi bạn lặp qua chúng, bạn tạo Segment khác mà có thể sẽ có chìa khóa giống như một hiện Segment trong bộ sưu tập của bạn:

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

Các lỗi hiển thị nếu bạn gán một cột như là duy nhất và cố gắng tiết kiệm cùng giá trị cho cột đó. Tôi có thể cung cấp cho bạn gợi ý nếu nó khả thi cho bạn. Để làm việc này, bạn có thể thêm cột tăng tự động mới có tên 'id' trong bảng phân đoạn và coi cột này là khóa

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

entity: 
id- key 
treatment_id 
segment_id 

Bây giờ, hãy thêm hoạt động của bạn. Và thực hiện thao tác chỉnh sửa và xóa đối tượng phân đoạn dựa trên id của phân đoạn.

2

Tôi có lỗi giống nhau khi chèn hàng vào bảng Oracle, giải quyết tệp edmx chỉnh sửa dưới dạng xml (nhấp chuột phải, mở bằng .., XML Editor) và thêm StoreGeneratedPattern="Identity" vào định nghĩa bảng.

Trước

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

Sau

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

này đang làm việc cho tôi. –

Các vấn đề liên quan