2009-03-11 59 views
8

Hola chicos, me he topado con algo que tal vez sea un error en el método de extensión .CopyToDataTable.Cómo lidiar con un error en System.Data.DataTableExtensions.CopyToDataTable()

Este método se utiliza importando (en VB.NET) System.Data.DataTableExtensions y luego llamando al método contra un IEnumerable. Haría esto si quiere filtrar una tabla de datos usando LINQ, y luego restaurar la DataTable al final.

es decir:

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 

En el ejemplo anterior, el "dónde" filtrado podría no producirá ningún resultado. Si esto sucede, CopyToDataTable arroja una excepción porque no hay DataRows.

¿Por qué?

El comportamiento correcto debe ser para devolver un DataTable con Rows.Count = 0.

¿Puede alguien pensar en una solución limpia para esto, de tal manera que todo aquel que invoque CopyToDataTable no tiene que ser consciente de ¿este problema?

System.Data.DataTableExtensions es una clase estática por lo que no puedo anular el comportamiento ... alguna idea? ¿Me he perdido algo?

aplausos

ACTUALIZACIÓN:

he presentado esto como un problema a Connect. Todavía me gustaría algunas sugerencias, pero si está de acuerdo conmigo, que podría votar la cuestión en Conectar mediante el enlace anterior

aplausos

Respuesta

2

Hasta Microsoft solucionar este problema, aquí hay un trabajo en torno a:

Cree su propio método de Extensión que use el método CopyToDataTable si hay DataRows, si no hay, entonces devuelve un DataTable vacío.

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

Creo que esto podría mejorarse ligeramente para usar '! Source.Any()' en lugar de 'Source.Count() == 0'. 'Any' se detendrá tan pronto como encuentre algún resultado. – row1

+0

Mucho más que un poco –

+2

Esto no es un error; el comportamiento es mucho por diseño y deliberado.Una de las primeras cosas que 'CopyToDataTable' hace es tomar una fila, encontrar la tabla subyacente y copiar las columnas en su nueva' DataTable'. Su solución crea un 'DataTable' vacío sin columnas. Puede salirse con la suya en un DataSource (no mirará la tabla si no tiene filas), pero en otros escenarios no puede. – Brian

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

.AsDataView().ToTable() devuelve una mesa vacía con la misma estructura que someDataTable si ahora hay filas devueltas desde .Where()

+0

genial, lo probaré, saludos, vince – andy

+0

un problema que veo con su extensión personalizada es el cheque de .Count. Si no me equivoco, .Count fuerza la lectura de toda la enumeración. Por lo tanto, si su recuento es, por ejemplo, 1000, está leyendo toda la enumeración y luego llamando a CopyToDataTable() que probablemente forzará otra lectura. ¿Ha considerado verificar si .GetEnumerator(). MoveNext() == true? Si esto es cierto, entonces la enumeración tiene al menos una fila, y eso es todo lo que le preocupa, no el recuento. – Vince

+0

buen punto Vince, tienes toda la razón. Lo actualizaré, ¡salud! – andy

1

me encontré con este problema hoy en día y llegaron a un workaround si ayuda.

Lo siento, pero el blog está en C#, pero acabo de utilizar un IEnumerable en la variable LINQ y compruebo .Current para ver si ha devuelto las filas.

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 
} 
Cuestiones relacionadas