sobota, 12 stycznia 2013

70-516 Bezpołączeniowy model cz. 2

W poprzednim poście rozpocząłem omawianie obiektu DataTable. W tym poście kontynuuje rozpoczęty temat.

Stan wiersza
Wiersze w obiekcie DataTable zmieniają swoje podczas całego życia obiektu. Sprawdzając właściwość RowState możemy dowiedzieć w jakim stanie jest obecnie wiersz. Wartości tego typu wyliczeniowego:
  • Detached - wiersz został stworzony, ale nie dodany do tabeli
  • Added - wiersz został stworzony i dodany do tabeli
  • Unchanged - stan wiersza nie zmienił się od ostatniego wywołania metody AcceptChanges; w momencie wywołania metody AcceptChanges wiersz przyjmuje ten stan
  • Modified - wiersz zmienia się w ten stan tylko jeżeli poprzednio miał stan Unchanged; po wywołaniu AcceptChanges wiersz zmienia swój stan na Unchanged
  • Deleted - wiersz przyjmuje ten stan gdy zostanie usunięty z tabeli
Przykład obrazujący zmianę stanów wiersza:

Code:
        static void Main(string[] args)
        {
            var clientTable = new DataTable("Client");
            var idColumn = new DataColumn("Id");
            idColumn.DataType = typeof (int);
            idColumn.Unique = true;
            idColumn.AllowDBNull = false;
            idColumn.Caption = "ID";
            idColumn.AutoIncrement = true;
            idColumn.AutoIncrementSeed = 1;
            idColumn.AutoIncrementStep = 1;
            clientTable.Columns.Add(idColumn);

            var firstNameColumn = new DataColumn("FirstName");
            firstNameColumn.DataType = typeof (string);
            firstNameColumn.MaxLength = 50;
            firstNameColumn.AllowDBNull = true;
            firstNameColumn.Caption = "Imię";
            clientTable.Columns.Add(firstNameColumn);

            clientTable.PrimaryKey = new DataColumn[] {idColumn};

            //Add new row by creating them first
            var row1 = clientTable.NewRow();
            row1["FirstName"] = "Jacek";
            Console.WriteLine(row1.RowState);
            clientTable.Rows.Add(row1);
            Console.WriteLine(row1.RowState);
            row1["FirstName"] = "Marek";
            Console.WriteLine(row1.RowState);
            row1.AcceptChanges();
            Console.WriteLine(row1.RowState);
            row1["FirstName"] = "Sebastian";
            Console.WriteLine(row1.RowState);
            row1.RejectChanges();
            Console.WriteLine(row1.RowState);
            Console.WriteLine(row1["FirstName"]);
            row1.Delete();
            Console.WriteLine(row1.RowState);
        }



Zarządzanie danymi w wierszu za pomocą wersji wiersza
DataTable może posiadać do trzech wersji danego wiersza: oryginalny (Original), obecny (Current) oraz zaplanowany (Proposed). Możliwe wartości przechowywane są w enumie DataRowVersion:
  • Current - obecna wartość; istnieje zawsze oprócz sytuacji w której usuniemy wiersz (próba pobrania zakończy się wyjątkiem)
  • Default - jeżeli DataRowState jest ustawiony na Added lub Modified - domyślna wartość to Current; jeżeli Deleted - rzucony zostanie wyjątek; jeżeli zostanie wywołana metoda BeginEdit - Proposed
  • Original - wartość załadowana do wiersza, lub ta od ostatniego wywołania metody AcceptChanges. Wartość ta nie jest ustawiana dopóki wiersz nie znajdzie się w stanie Modified, Unchanged, lub Deleted. Jeżeli wiersz jest w stanie Added, zostanie rzucony wyjątek VersionNotFound
  • Proposed - wartość w trakcie edycji wiersza. Jeżeli wiersz jest w stanie Deleted, zostanie rzucony wyjątek. Jeżeli metoda BeginEdit nie została wywołana, bądź też została wywołana na wierszu, który nie należy do DataTable, zostanie rzucony wyjątek VersionNotFound
Za pomocą metody HasVersion możemy w bezpieczny sposób sprawdzić czy dana wersja jest dostępna. Przykładowy kawałek kodu pozwalający na bezpieczne pobranie danej wersji wiersza:

Code:
            foreach (var rowVersion in Enum.GetNames(typeof(DataRowVersion)))
            {
                var enumValue = (DataRowVersion)Enum.Parse(typeof (DataRowVersion), rowVersion);
                if (row1.HasVersion(enumValue))
                {
                    Console.WriteLine(enumValue + " " + row1["FirstName", enumValue]);
                }
            }


Metody AcceptChanges oraz RejectChanges
Metody te, jak same ich nazwy mówią służą do akceptacji lub odrzucenia danych. Metody te są potrzebne, aby zmienić stan wiersza na Unchanged.
Po dokonaniu zmian wierszy, które zostały pobrane z źródła danych (np. bazy danych) należy wybrać tylko te wiersze, których stan to Modified. Wiesze które zostały zmodyfikowane możemy pobrać za pomocą metody GetChanges. Po zapisaniu zmian do źródła danych należy wywołać metodę AcceptChanges w celu zresetowania stanu wierszy przechowywanych w obiekcie DataTable.
Wywołanie AcceptChanges dodatkowo powoduje skopiowanie danych z wersji Current do wersji Original.
Wywołanie RejectChanges powoduje skopiowanie danych z wersji Original do Current.

Stan wiersza możemy także zmienić za pomocą dwóch dodatkowych metod:
  • SetAdded - dodany
  • SetModified - zmodyfikowany
Operacja taka może być przydatna gdy chcemy dane zapisać do innego źródła danych niż z którego oryginalnie zostały pobrane. Wystarczy w takim przypadku wywołać metodę SetAdded i przesłać taki obiekt DataTable do DataAdapter-a.
Metody te mają ograniczenie do wywoływania ich na wierszach, które są w stanie Unchanged. Jeżeli wiersz jest w innym stanie, zostanie rzucony wyjątek InvalidOperationExcetpion.
Dodatkowo metody te:
  • SetAdded - usuwa oryginalną wersjędanych
  • SetModified - nie modyfikuje wersji wiersza

Usuwanie wierszy i cofanie tej operacji
Wywołując metodę Delete na wierszu oznaczamy go do usunięcia. Następstwem jest usunięcie wersji danych Current oraz Proposed.
Jeżeli okaże się, że dany wiersz ma nie być usunięty, można użyć metody RejectChanges. Dane Original zostaną skopiowane do Current. Wiesz wraca do stanu sprzed ostatniego wywołania metody AcceptChanges, jednak wszystkie operacje wykonane po tej metodzie nie zostaną przywrócone.

Iteracja po danych zawartych w DataTable
Po obiekcie DataTable można iterować za pomocą pętli:

Code:
            var productTable = new DataTable("Products");
            productTable.Columns.Add("Id", typeof (int));
            productTable.Columns.Add("Name", typeof(string));
            productTable.Columns.Add("Price", typeof(decimal));
            productTable.Columns.Add("Amount", typeof(int));
            productTable.Rows.Add(new object[] { 1, "Laptops", 1678, 100 });
            productTable.Rows.Add(new object[] { 2, "Printers", 234.6d, 40 });
            productTable.Rows.Add(new object[] { 3, "Keybords", 70.30d, 130 });

            foreach (DataRow row in productTable.Rows)
            {
                foreach (DataColumn column in productTable.Columns)
                {
                    Console.Write(row[column.ColumnName] + "  ");
                }
                Console.WriteLine();
            }



Kopiowanie obiektów DataTable
Obiekty DataTable można kopiować za pomocą dwóch metod:
  • Copy - tworzy kopię zawierającą schemat i dane
  • Clone - kopiuje tylko schemę
Jeżeli zdecydujemy się na metodę Clone, możemy za pomocą metody ImportRow skopiować do niej wybrane rekordy (należy pamiętać, że schema tabel musi być taka sama). W przypadku gdy do tabeli docelowej będziemy próbowali skopiować rekord z kluczem głównym, który już w niej występuje, zostanie wyrzucony wyjątek ConstraintException.


Przykładowy kod do pobrania: http://sdrv.ms/X0ZixZ

Brak komentarzy:

Prześlij komentarz