2009-03-11 28 views
8

Hey guys, vì vậy tôi đã đi qua một cái gì đó mà có lẽ là một lỗ hổng trong phương pháp mở rộng .CopyToDataTable.Làm thế nào để đối phó với một lỗ hổng trong System.Data.DataTableExtensions.CopyToDataTable()

Phương pháp này được sử dụng bằng cách nhập (trong VB.NET) System.Data.DataTableExtensions và sau đó gọi phương thức chống lại một IEnumerable. Bạn sẽ làm điều này nếu bạn muốn lọc một Datatable bằng cách sử dụng LINQ, và sau đó khôi phục DataTable ở cuối.

tức là:

Imports System.Data.DataRowExtensions 
    Imports System.Data.DataTableExtensions 

    Public Class SomeClass 
      Private Shared Function GetData() As DataTable 
       Dim Data As DataTable 

       Data = LegacyADO.NETDBCall 


       Data = Data.AsEnumerable.Where(Function(dr) dr.Field(Of Integer)("SomeField") = 5).CopyToDataTable() 


       Return Data 

      End Function 
    End Class 

Trong ví dụ trên, "WHERE" lọc có thể không có kết quả. Nếu điều này xảy ra CopyToDataTable ném một ngoại lệ vì không có DataRows.

Tại sao?

Các hành vi chính xác nên được để trả về một DataTable với Rows.Count = 0.

bất cứ ai có thể nghĩ ra một cách giải quyết sạch vào đó, theo cách như vậy mà bất cứ ai gọi CopyToDataTable không nhất thiết phải nhận thức được vấn đề này?

System.Data.DataTableExtensions là lớp tĩnh nên tôi không thể ghi đè hành vi .... bất kỳ ý tưởng nào? Tôi đã bỏ lỡ một cái gì đó?

cổ vũ

UPDATE:

Tôi đã đệ trình này như là một vấn đề cần Connect. Tôi vẫn muốn một số gợi ý, nhưng nếu bạn đồng ý với tôi, bạn có thể bỏ phiếu lên vấn đề này tại Kết nối qua liên kết ở trên

cổ vũ

Trả lời

2

Cho đến khi Microsoft khắc phục vấn đề này, đây là một công trình xung quanh:

Tạo phương thức Extension của riêng bạn sử dụng phương thức CopyToDataTable nếu có DataRows, nếu không có, thì nó trả về một DataTable trống.

VB.NET

Imports System.Data 

Namespace CustomExtensions 
    Public Module DataRowExtensionsOverride 

     <System.Runtime.CompilerServices.Extension()> _ 
     Public Function CopyToDataTableOverride(Of T As DataRow)(ByVal Source As EnumerableRowCollection(Of T)) As DataTable 

      If Source.Count = 0 Then 
       Return New DataTable 
      Else 
       Return DataTableExtensions.CopyToDataTable(Of DataRow)(Source) 
      End If 

     End Function 

    End Module 
End Namespace 

C#;

public static class DataRowExtensionsOverride 
    { 

     public static DataTable CopyToDataTableOverride<T>(this IEnumerable<T> Source) where T : DataRow { 

      if (Source.Count() == 0) { 
       return new DataTable(); 
      } else { 
       return DataTableExtensions.CopyToDataTable<T>(Source); 
      } 
     } 
    } 
+1

Tôi nghĩ rằng điều này có thể được cải thiện một chút để sử dụng '! Source.Any()' thay vì 'Source.Count() == 0'. 'Bất kỳ' sẽ dừng lại ngay sau khi nó tìm thấy bất kỳ kết quả nào. – row1

+0

Nhiều hơn một chút –

+2

Đây không phải là lỗi; hành vi là rất nhiều bởi thiết kế và cố ý.Một trong những điều đầu tiên 'CopyToDataTable' thực hiện là lấy một hàng, tìm bảng bên dưới và sao chép các cột vào' DataTable' mới của bạn. Workaround của bạn tạo ra một 'DataTable' trống rỗng không có cột. Bạn có thể lấy đi với điều này trong một DataSource (nó sẽ không nhìn vào bảng nếu nó không có hàng), nhưng trong các tình huống khác bạn không thể. – Brian

12
someDataTable.AsEnumerable().Where(r => r.Field<string>("SomeField") == "SomeValue").AsDataView().ToTable(); 

.AsDataView().ToTable() trả về một bảng trống với cấu trúc tương tự như someDataTable nếu bây giờ có hàng trở về từ .Where()

+0

thật tuyệt, tôi sẽ dùng thử, cổ vũ vince – andy

+0

một vấn đề tôi thấy với tiện ích tùy chỉnh của bạn là kiểm tra .Count. Nếu tôi không nhầm, .Count buộc một đọc của toàn bộ liệt kê. Vì vậy, nếu đếm của bạn là nói, 1000, sau đó bạn đang đọc toàn bộ liệt kê sau đó gọi CopyToDataTable() mà có thể buộc đọc khác. Bạn đã xem xét kiểm tra xem .GetEnumerator(). MoveNext() == true? Nếu điều này là đúng, thì điều tra có ít nhất một hàng, và đó là tất cả những gì bạn quan tâm, chứ không phải đếm. – Vince

+0

vince điểm tốt, bạn hoàn toàn đúng. Tôi sẽ cập nhật nó, chúc mừng! – andy

1

Tôi đã xem qua vấn đề này hôm nay và làm việc ra một workaround nếu nó giúp.

Xin lỗi, nhưng blog nằm trong C#, nhưng tôi chỉ sử dụng một IEnumerable trên biến LINQ và kiểm tra. Hiện tại để xem nếu nó đã trả về bất kỳ hàng nào.

0
DataTable SearchDT = (DataTable)ViewState["SearchDT"]; 
DataTable NewDT = SearchDT.Select("BSerialNo='" + SerialNo + "' and BBranch='" + Branch + "' and Warehouse='" + WareHouse + "' and Buffer_ModelNo='" + PartNo + "'").CopyToDataTable(); 
// first get an array of DataRows ' 
if ((NewDT.Rows.Count > 0)) 
{ 
    //first check to see if the array has rows 
    DataTable dt = NewDT; 
    PopUpGrdView.DataSource = dt; 
    PopUpGrdView.DataBind(); 
    //dt now exists and contains rows 
} 
Các vấn đề liên quan