2012-12-27 61 views
9

Tôi đang viết một thuật toán ngắn mà phải so sánh hai DataSets, để sự khác biệt giữa cả hai có thể được xử lý tiếp. Tôi đã cố hoàn thành mục tiêu này bằng cách hợp nhất hai DataSets này và nhận được các thay đổi kết quả thành một Số liệu mới.nhận được sự khác biệt trong 2 DataSets C#

Phương pháp của tôi trông như thế này:

private DataSet ComputateDiff(DataSet newVersion, DataSet oldVersion) 
    { 
     DataSet diff = null; 
     oldVersion.Merge(newVersion); 
     bool foundChanges = oldVersion.HasChanges(); 
     if (foundChanges) 
     { 
      diff = oldVersion.GetChanges(); 
     } 
     return diff; 
    } 

Kết quả của foundChanges luôn là sai, mặc dù hai DataSet có giá trị khác nhau trong đó. Cả hai DataSets đều có cùng một đường cong. Chúng bao gồm ba DataTables là kết quả của ba truy vấn trong một cơ sở dữ liệu. Việc hợp nhất hoạt động tốt không có vấn đề với điều đó.

Câu hỏi của tôi là: Có bất kỳ lời giải thích hợp lý tại sao biến foundChanges luôn là sai và nếu không LINQ sẽ cung cấp một giải pháp thích hợp cho vấn đề này hoặc làm tôi phải xác định những thay đổi bằng cách duyệt qua DataSets

Dưới đây là một số thông tin thêm: Ngôn ngữ lập trình là C# Tôi đang sử dụng .Net framework 4.0 Tôi đang phát triển trên Máy tính WindowsDữ liệu như được đề cập đến từ Cơ sở dữ liệu (MSSQL Server 2012 express) DataSets của tôi hoặc DataTables thiên đường 't có bất kỳ PK của xa như tôi biết.

Cảm ơn trước

+1

Thông thường những gì bạn sẽ làm là lấy tập dữ liệu oldVersion và sửa đổi nó. Sau đó oldVersion sẽ chứa tất cả các thay đổi mới. Sau đó bạn có thể gọi DataSet diff = oldVersion.GetChanges(). –

+1

Bạn có thể thấy điều này hữu ích: http://stackoverflow.com/a/7518025/211627 – JDB

Trả lời

3

Tôi nghĩ rằng vấn đề là bạn không hiểu .NET DataSets. Một DataTable giữ lại bản sao "gốc" của mỗi giá trị được nạp vào nó. Khi một giá trị được thay đổi, DataTable có thể phát hiện sự thay đổi. Tương tự như vậy, DataTable theo dõi các hàng đã được thêm vào hoặc bị xóa. Chức năng HasChanges() chỉ đơn giản là bóc tách qua DataTables và kiểm tra xem nếu có gì thay đổi (giá trị thay đổi, hàng mới, hàng xóa, vv)

Xem tài liệu MSDN:
http://msdn.microsoft.com/en-us/library/system.data.dataset.haschanges.aspx

So sánh hai tập dữ liệu là khôn lanh, và tôi không biết về bất kỳ chức năng tích hợp nào để xử lý điều này (vì mọi lập trình viên sẽ có định nghĩa riêng về "sự tương đương").

Xem:

Đoạn code dưới đây sẽ so sánh hai DataTables bằng cách tìm kiếm thêm/hàng bị xóa dựa trên một cột chính và sửa đổi hàng bởi so sánh các giá trị của các hàng phù hợp (một lần nữa, dựa trên khóa). Nó sẽ là khá tầm thường để mở rộng này để so sánh DataSets (bằng cách so sánh các bảng được đặt tên tương tự giữa DataSets).

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data; 

namespace DataSetComparison 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      var l_table1 = new DataTable(); 
      l_table1.Columns.Add("Key", typeof(int)); 
      l_table1.Columns.Add("Name", typeof(string)); 
      l_table1.Columns.Add("Age", typeof(int)); 

      var l_table2 = new DataTable(); 
      l_table2.Columns.Add("Key", typeof(int)); 
      l_table2.Columns.Add("Name", typeof(string)); 
      l_table2.Columns.Add("Age", typeof(int)); 

      l_table1.Rows.Add(l_table1.NewRow()); 
      l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 0; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Alfred Harisson"; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 36; 
      l_table1.Rows.Add(l_table1.NewRow()); 
      l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 1; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Matthew George"; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 41; 
      l_table1.Rows.Add(l_table1.NewRow()); 
      l_table1.Rows[l_table1.Rows.Count - 1]["Key"] = 2; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Name"] = "Franklin Henry"; 
      l_table1.Rows[l_table1.Rows.Count - 1]["Age"] = 33; 

      l_table2.Rows.Add(l_table2.NewRow()); 
      l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 0; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Alfred Harisson"; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 36; 
      l_table2.Rows.Add(l_table2.NewRow()); 
      l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 1; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Matthew George"; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 42; // Record 1 "modified" 
      // Record 2 "deleted" 
      // Record 3 "added": 
      l_table2.Rows.Add(l_table2.NewRow()); 
      l_table2.Rows[l_table2.Rows.Count - 1]["Key"] = 3; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Name"] = "Lester Kulick"; 
      l_table2.Rows[l_table2.Rows.Count - 1]["Age"] = 33; 

      // Using table 1 as the control, find changes in table 2 

      // Find deleted rows: 
      var l_table2Keys = l_table2.Select().Select((r) => (int) r["Key"]); 
      var l_deletedRows = l_table1.Select().Where((r) => !l_table2Keys.Contains((int) r["Key"])); 

      foreach (var l_deletedRow in l_deletedRows) 
       Console.WriteLine("Record " + l_deletedRow["Key"].ToString() + " was deleted from table 2."); 

      // Find added rows: 
      var l_table1Keys = l_table1.Select().Select((r) => (int) r["Key"]); 
      var l_addedRows = l_table2.Select().Where((r) => !l_table1Keys.Contains((int) r["Key"])); 

      foreach (var l_addedRow in l_addedRows) 
       Console.WriteLine("Record " + l_addedRow["Key"].ToString() + " was added to table 2."); 

      // Find modified rows: 
      var l_modifiedRows = l_table2.Select() 
             .Join(
              l_table1.Select(), 
              r => (int) r["Key"], 
              r => (int) r["Key"], 
              (r1, r2) => new 
               { 
                Row1 = r1, 
                Row2 = r2 
               }) 
             .Where(
              values => !(values.Row1["Name"].Equals(values.Row2["Name"]) && 
                 values.Row1["Age"].Equals(values.Row2["Age"]))) 
             .Select(values => values.Row2); 

      foreach (var l_modifiedRow in l_modifiedRows) 
       Console.WriteLine("Record " + l_modifiedRow["Key"].ToString() + " was modified in table 2."); 

      Console.WriteLine("Press any key to quit..."); 
      Console.ReadKey(true); 

     } 
    } 
} 

điều khiển đầu ra:

Ghi 2 đã bị xóa từ bảng 2.
Ghi 3 được bổ sung vào bảng 2.
ghi 1 đã được sửa đổi trong bảng 2.

+0

Chỉ trong tìm kiếm .contains, .exists có thể hữu ích cho bạn. –

+0

Cyborgx37 là đúng, bạn không thể dễ dàng làm điều này. Bạn sẽ cần phải có kiến ​​thức về các khóa của tập dữ liệu, nếu không bạn sẽ không thể biết liệu thay đổi là bản cập nhật, xóa hay chèn. –

0

Nếu lược đồ bộ dữ liệu cả hai đều giống nhau thì bạn có thể thử bên dưới một

Dataset dsTest1 
DataSet dsTest2 
DataSet dsFinal; 
dsFinal.Merge(dsTest1); 
dsFinal.AcceptChanges(); 
dsFinal.Merge(dsTest2); 
DifferenceDataSet = dsFinal.GetChanges() 

Nếu lược đồ của cả hai bộ dữ liệu khác nhau thì bạn phải tự làm điều đó.

+0

Tại sao tôi tiếp tục thấy mọi người nói rằng Merge + GetChanges hoạt động, khi nó không? –

-1

Như bạn có thể thấy từ một số câu trả lời khác, không dễ để có được sự khác biệt của hai DataSets.

Đó là mục đích của DataSet.GetChanges(). Nếu bạn bắt đầu với tập dữ liệu và thực hiện thay đổi trực tiếp cho tập dữ liệu đó (nghĩa là khi người dùng cập nhật ô, khi người dùng gửi biểu mẫu, v.v ...) thì Số liệu theo dõi các thay đổi. Bằng cách này bạn có thể gọi DataSet.GetChanges() để nhận các thay đổi (hoặc sự khác biệt). Sau đó, bạn chỉ có thể xử lý các thay đổi.

Thật khó để lấy số liệu ban đầu và tập dữ liệu cuối cùng và nhận được sự khác biệt. Việc hợp nhất tập dữ liệu cuối cùng với tập dữ liệu cũ không có ý nghĩa, vì tập dữ liệu cuối cùng là kết quả của quá trình hợp nhất.

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