Prosty sposób na skopiowanie lub sklonowanie DataRow?


118

Szukam prostego sposobu na utworzenie klonu DataRow. Coś jak zrobienie migawki tego rzędu i zapisanie go. Wartości oryginalnego wiersza można następnie zmienić, ale nadal mamy inną zapisaną kopię, która się nie zmienia. Czy to jest właściwy sposób?

DataRow Source, Destination;
// Assume we create some columns and fill them with values
Destination.ItemArray = Source.ItemArray;

Czy spowoduje to ustawienie odniesienia ItemArray w Snapshot tak, aby wskazywało na ten w źródle, czy faktycznie tworzy oddzielną kopię? Powinienem to zrobić zamiast tego?

Destination.ItemArray = Source.ItemArray.Clone();

EDYCJA: Nie sądzę, aby drugi fragment kodu faktycznie się kompilował.


Nie jestem pewien, czy rozumiem, chcesz skopiować wiersz danych z jednej tabeli do drugiej? Jeśli tak, to uważam, że szukasz DataTable.ImportRow.
— Mo Patel,

Ok, widzę, że moje pytanie wymaga teraz ponownej odpowiedzi
— Paul Matthews

2
Zauważ, że w niektórych scenariuszach może nie być konieczne robienie tego, ponieważ sam datarow obsługuje edycję transakcyjną za pomocą BeginEdit / EndEdit / CancelEdit; możesz również wywołać na nim .RejectChanges.
— peterG

Odpowiedzi:


185

Możesz użyć ImportRowmetody, aby skopiować wiersz z DataTable do DataTable z tym samym schematem:

var row = SourceTable.Rows[RowNum];
DestinationTable.ImportRow(row);

Aktualizacja:

Wierzę, że dzięki Twojej nowej edycji:

var desRow = dataTable.NewRow();
var sourceRow = dataTable.Rows[rowNum];
desRow.ItemArray = sourceRow.ItemArray.Clone() as object[];

będzie działać


Najwyraźniej Clone () zapewnia tylko skróconą kopię. Myślisz, że to wystarczy do stworzenia identycznej kopii, czy też potrzebny jest głęboki klon?
— Paul Matthews

5
@PaulMatthews: Szczęśliwie DataTable zawiera typy wartości, a nie ref typ, więc płytkie kopię w rodzaju wartości os samo z głębokim kopii
— cuongle

16
Dla osób, które znajdą ten post, dodam następujące, ponieważ często mnie pytano, więc myślę, że inni ludzie mogą być zdezorientowani. Klonuj kopiuj tylko strukturę, Kopiuj kopiuj strukturę, a następnie dane. Mówi się, że innym prostym sposobem kopiowania danych po utworzeniu instancji obu tabel jest utworzenie nowego wiersza w tabeli docelowej i użycie następującego: destRow.ItemArray = sourceRow.ItemArraynastępnie proste dodanie wiersza z powrotem za pomocądestTable.Rows.Add(destRow);
— Franck

1
Próbuję użyć tej metody, aby uzyskać klon datarow. Wykonuję następujące kroki, następnie usuwam datatable, który zawiera wiersz źródłowy, a teraz mam wiersz źródłowy z pustymi polami.
— Sergеу Isupov

Okazało się, że metoda ImportRow zadziałała u mnie, podczas gdy metoda NewRow nie.
— OldDog

2

Uwaga: pomocna odpowiedź Cuongle zawiera wszystkie składniki, ale rozwiązanie można usprawnić (nie ma potrzeby .ItemArray) i można je przeformułować, aby lepiej dopasować zadane pytanie.

Aby utworzyć (izolowany) klon danej System.Data.DataRowinstancji , możesz wykonać następujące czynności:

// Assume that variable `table` contains the source data table.

// Create an auxiliary, empty, column-structure-only clone of the source data table.
var tableAux = table.Clone();
// Note: .Copy(), by contrast, would clone the data rows also.

// Select the data row to clone, e.g. the 2nd one:
var row = table.Rows[1];

// Import the data row of interest into the aux. table.
// This creates a *shallow clone* of it.
// Note: If you'll be *reusing* the aux. table for single-row cloning later, call
//       tableAux.Clear() first.
tableAux.ImportRow(row);

// Extract the cloned row from the aux. table:
var rowClone = tableAux.Rows[0];

Uwaga: Wykonywane jest płytkie klonowanie , które działa tak jak jest z wartościami kolumn, które są instancjami typu wartości , ale potrzeba więcej pracy, aby również utworzyć niezależne kopie wartości kolumn zawierających instancje typu referencyjnego (a tworzenie takich niezależnych kopii nie zawsze jest możliwe ).


1

Wygląda na to, że nie chcesz zachować całego DataTable jako kopii, ponieważ potrzebujesz tylko kilku wierszy, prawda? Jeśli masz kreterię, którą możesz określić za pomocą zaznaczenia w tabeli, możesz skopiować tylko te wiersze do dodatkowej kopii zapasowej tablicy DataRow, takiej jak

DataRow[] rows = sourceTable.Select("searchColumn = value");

Funkcja .Select () ma kilka opcji, a tę można np. Odczytać jako SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Następnie możesz zaimportować żądane wiersze, jak opisano powyżej.

targetTable.ImportRows(rows[n])

... dla dowolnego poprawnego n, które chcesz, ale kolumny muszą być takie same w każdej tabeli.

Kilka rzeczy, które powinieneś wiedzieć o ImportRow, to fakt, że podczas używania kluczy podstawowych będą występować błędy!

Najpierw chciałem sprawdzić, czy istnieje już wiersz, który również nie powiódł się z powodu braku klucza podstawowego, ale potem sprawdzenie zawsze kończyło się niepowodzeniem. W końcu zdecydowałem się całkowicie wyczyścić istniejące wiersze i ponownie zaimportować te, które chciałem.

Druga kwestia pomogła zrozumieć, co się dzieje. Sposób, w jaki używam funkcji importu, polega na duplikowaniu wierszy z wymienionym wpisem w jednej kolumnie. Zdałem sobie sprawę, że zawsze się to zmieniało i nadal było to odniesienie do wiersza w tablicy. Najpierw musiałem zaimportować oryginał, a następnie zmienić wpis, który chciałem.

W odwołaniu wyjaśniono również błędy klucza podstawowego, które pojawiły się, gdy po raz pierwszy próbowałem zaimportować wiersz, ponieważ naprawdę został podwojony.


-4

Aby jednak upewnić się, że nowy wiersz jest dostępny w nowej tabeli, musisz zamknąć tabelę:

DataTable destination = new DataTable(source.TableName);
destination = source.Clone();
DataRow sourceRow = source.Rows[0];
destination.ImportRow(sourceRow);

3
Jaki jest sens pierwszej linii kodu, jeśli druga linia kodu ponownie przypisuje zmienną?
— Erik Philips,

Ta odpowiedź przydałaby się więcej wyjaśnień (i nie wiem, co oznacza konieczność zamknięcia tabeli ), a @ErikPhilips ma rację ( DataTable destination = source.Clone()powinien zrobić), ale poza tym ta odpowiedź jest całkowicie w porządku, a nawet lepsza niż .ItemArraypodejście w zaakceptowanej odpowiedzi.
— mklement0
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.