이것은 DataTable API의 버그입니까? 변경 사항은 "잘못된 시퀀스"로 저장/실행됩니다.

StackOverflow https://stackoverflow.com/questions/1027095

  •  06-07-2019
  •  | 
  •  

문제

편집 : 이것이 .NET 버그라고 생각하는지 여부에 관계없이 모든 의견에 감사 할 것입니다.

다음 시나리오를 단순화 할 수있는 버그가 있습니다.

기본 키를 연속적으로 유지 해야하는 데이터 가능이 있습니다. 예를 들어 다른 행 사이에 행을 삽입하면 먼저 후속 행의 ID를 증가시켜 공간을 만들고 행을 삽입해야합니다.

행을 삭제하면 테이블의 행에 남은 간격을 채우기 위해 후속 행의 ID를 줄여야합니다.

올바르게 작동하는 테스트 케이스

ID 1, 2 및 3으로 테이블에서 3 줄로 시작하십시오.

그런 다음 id = 2를 삭제하고 id = 3을 설정합니다. id = 3 (간격을 채우기 위해); 이것은 올바르게 작동합니다. DataTable.getChanges ()에는 삭제 된 행이 포함 된 다음 수정 된 행; dataadapter.update (테이블)를 실행하면 잘 실행됩니다.

작동하지 않는 테스트 케이스

그러나 2 행 (ID 1 및 2)으로 시작하면 ID = 3을 ID = 2로 설정하고 ID = 2를 삽입 한 다음 커밋 (또는 수락) 변경 사항을 변경하십시오. 이것은 이제 첫 번째 테스트와 동일한 상태 여야합니다.

그런 다음 이전과 동일한 단계를 수행합니다. 즉, id = 2를 삭제하고 id = 3을 설정하지만 이제 dataTable.getChanges ()는 잘못된 순서입니다. 첫 번째 행은 수정 된 행이고 두 번째 행은 삭제 된 행입니다. 그런 다음 DataAdapter.Update (테이블)를 시도하면 기본 키 위반이 제공됩니다. 삭제하기 전에 이미 기존 행으로 행을 수정하려고 시도했습니다.

해결 방법

문제에 대한 해결 방법을 생각할 수 있습니다. 즉, 삭제 된 행이 먼저 커밋 한 다음 행을 수정 한 다음 행을 추가 할 수 있습니다. 그러나 왜 이런 일이 일어나고 있습니까? 다른 해결책이 있습니까?

나는 사전에 비슷한 "문제"를 보았다고 생각합니다. 일부 항목을 추가하면 삭제하고 다시 삽입하면 추가 한 순서가되지 않습니다 (사전을 열거 할 때).

다음은 문제를 보여주는 두 가지 수녀 테스트입니다.

[Test]
public void GetChanges_Working()
{
    // Setup ID table with three rows, ID=1, ID=2, ID=3
    DataTable idTable = new DataTable();
    idTable.Columns.Add("ID", typeof(int));

    idTable.PrimaryKey = new DataColumn[] { idTable.Columns["ID"] };

    idTable.Rows.Add(1);
    idTable.Rows.Add(2);
    idTable.Rows.Add(3);

    idTable.AcceptChanges();

    // Delete ID=2, and move old ID=3 to ID=2
    idTable.Select("ID = 2")[0].Delete();
    idTable.Select("ID = 3")[0]["ID"] = 2;

    // Debug GetChanges
    foreach (DataRow row in idTable.GetChanges().Rows)
    {
        if (row.RowState == DataRowState.Deleted)
            Console.WriteLine("Deleted: {0}", row["ID", DataRowVersion.Original]);
        else
            Console.WriteLine("Modified: {0} = {1}", row["ID", DataRowVersion.Original], row["ID", DataRowVersion.Current]);
    }

    // Check GetChanges
    Assert.AreEqual(DataRowState.Deleted, idTable.GetChanges().Rows[0].RowState, "1st row in GetChanges should be deleted row");
    Assert.AreEqual(DataRowState.Modified, idTable.GetChanges().Rows[1].RowState, "2nd row in GetChanges should be modified row");
}

산출:

Deleted: 2
Modified: 3 = 2

1 passed, 0 failed, 0 skipped, took 4.27 seconds (NUnit 2.4).

다음 테스트 :

[Test]
public void GetChanges_NotWorking()
{
    // Setup ID table with two rows, ID=1, ID=2
    DataTable idTable = new DataTable();
    idTable.Columns.Add("ID", typeof(int));

    idTable.PrimaryKey = new DataColumn[] { idTable.Columns["ID"] };

    idTable.Rows.Add(1);
    idTable.Rows.Add(2);

    idTable.AcceptChanges();

    // Move old ID=2 to ID=3, and add ID=2
    idTable.Select("ID = 2")[0]["ID"] = 3;
    idTable.Rows.Add(2);

    idTable.AcceptChanges();

    // Delete ID=2, and move old ID=3 to ID=2
    idTable.Select("ID = 2")[0].Delete();
    idTable.Select("ID = 3")[0]["ID"] = 2;

    // Debug GetChanges
    foreach (DataRow row in idTable.GetChanges().Rows)
    {
        if (row.RowState == DataRowState.Deleted)
            Console.WriteLine("Deleted: {0}", row["ID", DataRowVersion.Original]);
        else
            Console.WriteLine("Modified: {0} = {1}", row["ID", DataRowVersion.Original], row["ID", DataRowVersion.Current]);
    }

    // Check GetChanges
    Assert.AreEqual(DataRowState.Deleted, idTable.GetChanges().Rows[0].RowState, "1st row in GetChanges should be deleted row");
    Assert.AreEqual(DataRowState.Modified, idTable.GetChanges().Rows[1].RowState, "2nd row in GetChanges should be modified row");
}

산출:

Modified: 3 = 2
Deleted: 2
TestCase 'GetChanges_NotWorking'
failed: 
  1st row in GetChanges should be deleted row
  Expected: Deleted
  But was:  Modified
도움이 되었습니까?

해결책

그것은 버그가 아닙니다. 요점은 당신이 (매우) 비표준적인 방식으로 ID를 사용하고 있다는 것입니다. 두 가지 답변 :

1) DataTable.GetChanges (DatArowState.Modified)를 사용하여 업데이트를 순서대로 처리합니다 (삭제, 수정, 삽입). 이것은 마스터/세부 관계와도 관련이 있습니다 (.NET 3.0 이전)

2) 디자인을 다시 생각하십시오. 일반적으로 ID는 불변이어야하고 갭 등을 허용해야합니다. 이렇게하면 모든 데이터베이스 작업이 훨씬 더 안정적이고 훨씬 쉬워집니다. 다른 열을 사용하여 사용자에게 제시 할 순차적 번호를 유지할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top