Cách đơn giản để sao chép hoặc nhân bản một DataRow?


118

Tôi đang tìm một cách đơn giản để tạo bản sao của DataRow. Kiểu giống như chụp nhanh Hàng đó và lưu nó. Các giá trị của Hàng gốc sau đó có thể tự do thay đổi nhưng chúng tôi vẫn có một bản sao đã lưu khác không thay đổi. Đây có phải là cách chính xác để làm điều đó?

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

Điều này sẽ chỉ đặt tham chiếu ItemArray của Snapshot trỏ đến tham chiếu trong Nguồn hay nó thực sự tạo một bản sao riêng? Tôi có nên làm điều này thay thế?

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

CHỈNH SỬA: Tôi không nghĩ đoạn mã thứ hai thực sự biên dịch.


Tôi không chắc mình hiểu, bạn muốn sao chép datarow từ bảng này sang bảng khác? Nếu vậy, tôi tin rằng sử dụng DataTable.ImportRow là thứ bạn đang theo đuổi.
Mo Patel

Ok, tôi thấy rằng nhu cầu của câu hỏi của tôi lại làm việc tại
Paul Matthews

2
Lưu ý rằng trong một số trường hợp, bạn có thể không cần thực hiện việc này vì bản thân datarow hỗ trợ chỉnh sửa giao dịch với BeginEdit / EndEdit / CancelEdit; bạn cũng có thể gọi .RejectChanges trên đó.
peterG

Câu trả lời:


185

Bạn có thể sử dụng ImportRowphương pháp để sao chép Hàng từ DataTable sang DataTable với cùng một lược đồ:

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

Cập nhật:

Với Chỉnh sửa mới của bạn, tôi tin rằng:

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

sẽ làm việc


Rõ ràng là Clone () chỉ cung cấp một bản sao cạn. Bạn có nghĩ rằng như vậy là đủ để tạo ra một bản sao y hệt hay là một bản sao sâu?
Paul Matthews

5
@PaulMatthews: May mắn DataTable chứa các loại giá trị, không ref loại, bản sao để nông ở kiểu giá trị os cùng với bản sao sâu
Cuongle

16
Đối với những người tìm thấy bài đăng này, tôi sẽ thêm phần sau vì tôi đã được hỏi thường xuyên nên tôi đoán những người khác có thể nhầm lẫn. Sao chép chỉ sao chép cấu trúc, Sao chép sao chép cấu trúc sau đó sao chép dữ liệu. Đang được nói một cách dễ dàng để sao chép dữ liệu một lần cả hai bảng khởi tạo là tạo ra một hàng mới trong bảng đích và sử dụng như sau: destRow.ItemArray = sourceRow.ItemArrayadd sau đó đơn giản phía sau hàng vớidestTable.Rows.Add(destRow);
Franck

1
Tôi đang cố gắng sử dụng phương pháp này để nhận bản sao của một tập tin dữ liệu. Tôi làm theo các bước sau, sau đó tôi xóa dữ liệu chứa hàng nguồn và bây giờ tôi có một hàng nguồn với các trường trống.
Sergеу Isupov

Tôi thấy rằng việc sử dụng phương thức ImportRow có hiệu quả với tôi, trong khi phương pháp NewRow thì không.
OldDog

2

Lưu ý: câu trả lời helfpul của cuongle có tất cả các thành phần, nhưng giải pháp có thể được sắp xếp hợp lý (không cần thiết .ItemArray) và có thể được điều chỉnh lại để phù hợp hơn với câu hỏi được hỏi.

Để tạo (cô lập) bản sao của một trao System.Data.DataRowdụ , bạn có thể làm những điều sau đây:

// 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];

Lưu ý: Sao chép nông được thực hiện , hoạt động như hiện nay với các giá trị cột là các thể hiện kiểu giá trị , nhưng sẽ cần nhiều công việc hơn để tạo các bản sao độc lập của các giá trị cột chứa các thể hiện kiểu tham chiếu (và không phải lúc nào cũng có thể tạo các bản sao độc lập như vậy ).


1

Có vẻ như bạn không muốn giữ toàn bộ DataTable như một bản sao, vì bạn chỉ cần một số hàng, phải không? Nếu bạn có một creteria, bạn có thể chỉ định bằng một lựa chọn trên bảng, bạn có thể chỉ sao chép các hàng đó vào một mảng dự phòng bổ sung của DataRow như

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

Hàm .Select () có một số tùy chọn và ví dụ này có thể được đọc như một SQL

SELECT * FROM sourceTable WHERE searchColumn = value;

Sau đó, bạn có thể nhập các hàng bạn muốn như mô tả ở trên.

targetTable.ImportRows(rows[n])

... cho bất kỳ n hợp lệ nào bạn thích, nhưng các cột cần giống nhau trong mỗi bảng.

Một số điều bạn nên biết về ImportRow là sẽ có lỗi trong thời gian chạy khi sử dụng khóa chính!

Đầu tiên, tôi muốn kiểm tra xem một hàng đã tồn tại mà cũng không thành công do thiếu khóa chính, nhưng sau đó kiểm tra luôn không thành công. Cuối cùng, tôi quyết định xóa hoàn toàn các hàng hiện có và nhập lại các hàng tôi muốn.

Vấn đề thứ hai đã giúp hiểu điều gì sẽ xảy ra. Cách tôi đang sử dụng hàm nhập là sao chép các hàng với một mục được trao đổi trong một cột. Tôi nhận ra rằng nó luôn thay đổi và nó vẫn là một tham chiếu đến hàng trong mảng. Đầu tiên tôi phải nhập bản gốc và sau đó thay đổi mục nhập mà tôi muốn.

Tham chiếu cũng giải thích các lỗi khóa chính xuất hiện khi tôi lần đầu tiên cố gắng nhập hàng vì nó thực sự được tăng gấp đôi.


-4

Nhưng để đảm bảo rằng hàng mới của bạn có thể truy cập được trong bảng mới, bạn cần đóng bảng:

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

3
Điểm của dòng mã đầu tiên là gì nếu dòng mã thứ hai gán lại biến?
Erik Philips

Câu trả lời này có thể sử dụng nhiều lời giải thích hơn (và tôi không biết cần phải đóng bảng nghĩa là gì) và @ErikPhilips có lý ( DataTable destination = source.Clone()nên làm), nhưng nếu không thì câu trả lời này hoàn toàn ổn và thậm chí thích hợp hơn với .ItemArraycách tiếp cận trong câu trả lời được chấp nhận.
mklement0
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.