2009-03-11 16 views
8

Ciao ragazzi, quindi mi sono imbattuto in qualcosa che è forse un difetto nel metodo Extension .CopyToDataTable.Come gestire un difetto in System.Data.DataTableExtensions.CopyToDataTable()

Questo metodo è utilizzato da Importazione (in VB.NET) System.Data.DataTableExtensions e quindi chiamando il metodo su un oggetto IEnumerable. Lo si farebbe se si desidera filtrare un Datatable utilizzando LINQ e quindi ripristinare il DataTable alla fine.

cioè:

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 

Nell'esempio precedente, il "dove" filtraggio potrebbe restituire risultati. Se ciò accade, CopyToDataTable genera un'eccezione perché non esistono DataRows.

Perché?

Il comportamento corretto dovrebbe essere quello di restituire un DataTable con Rows.Count = 0.

Qualcuno può pensare a una soluzione pulita per questo, in modo tale che chi chiama CopyToDataTable non deve essere a conoscenza di questa edizione?

System.Data.DataTableExtensions è una classe statica, quindi non posso ignorare il comportamento ... qualche idea? Ho perso qualcosa?

applausi

UPDATE:

Ho presentato questo come un problema da Connect. Vorrei ancora alcuni suggerimenti, ma se siete d'accordo con me, si potrebbe votare la questione in Connetti tramite il link qui sopra

applausi

risposta

2

Fino Microsoft risolvere il problema, qui è un lavoro intorno:

Crea il tuo metodo di estensione che usa il metodo CopyToDataTable se ci sono DataRows, se non ci sono, restituisce un DataTable vuoto.

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

Penso che questo potrebbe essere leggermente migliorato per usare '! Source.Any()' invece di 'Source.Count() == 0'. 'Any' si fermerà non appena avrà trovato alcun risultato. – row1

+0

Molto più che leggermente –

+2

Questo non è un bug; il comportamento è molto designato e deliberato.Una delle prime cose che "CopyToDataTable" fa è prendere una riga, trovare la tabella sottostante e copiare le colonne nel nuovo 'DataTable'. La tua soluzione alternativa crea un 'DataTable' vuoto senza colonne. Puoi farla franca in un DataSource (non guarderà la tabella se non ha righe), ma in altri scenari non puoi. – Brian

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

.AsDataView().ToTable() restituisce una tabella vuota con la stessa struttura di someDataTable se ora ci sono le righe restituite da .Where()

+0

cool, ci proverò, ciao venerdi – andy

+0

un problema che vedo con la tua estensione personalizzata è il controllo per .Count. Se non mi sbaglio, .Count forza la lettura dell'intera enumerazione. Pertanto, se il tuo conteggio è 1000, allora stai leggendo l'intera enumerazione, quindi chiama CopyToDataTable() che probabilmente impone un'altra lettura. Hai considerato di controllare se .GetEnumerator(). MoveNext() == true? Se questo è vero, allora l'enumerazione ha almeno una riga, e questo è tutto ciò che ti preoccupa, non il conteggio. – Vince

+0

buon punto vince, hai perfettamente ragione. Lo aggiorno, evviva! – andy

1

mi sono imbattuto in questo problema oggi e hanno elaborato un workaround se aiuta.

Siamo spiacenti, ma il blog è in C#, ma ho appena utilizzato un oggetto IEnumerable sulla variabile LINQ e ho controllato .Current per vedere se aveva restituito qualsiasi riga.

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 
}