2009-03-11 6 views
8

Hé les gars, alors je suis venu à travers quelque chose qui est peut-être une faille dans la méthode d'extension .CopyToDataTable.Comment faire face à une faille dans System.Data.DataTableExtensions.CopyToDataTable()

Cette méthode est utilisée par l'importation (en VB.NET) System.Data.DataTableExtensions puis appeler la méthode contre un IEnumerable. Vous le feriez si vous souhaitez filtrer une Datatable à l'aide de LINQ, puis restaurer le DataTable à la fin.

i.e.:

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 

Dans l'exemple ci-dessus, le filtrage "WHERE" pourrait retourner aucun résultat. Si cela se produit, CopyToDataTable lève une exception car il n'y a pas de DataRows.

Pourquoi?

Le comportement correct devrait être de retourner un DataTable avec Rows.Count = 0.

Quelqu'un peut-il penser à une solution propre à cela, de telle sorte que quiconque invoquera CopyToDataTable ne pas être au courant de ce problème?

System.Data.DataTableExtensions est une classe statique je ne peux pas remplacer le comportement .... des idées? Ai-je manqué quelque chose?

acclamations

MISE À JOUR:

J'ai présenté cela comme un problème à Connect. Je voudrais encore quelques suggestions, mais si vous êtes d'accord avec moi, vous pourriez voter la question à se connecter via le lien ci-dessus

acclamations

Répondre

2

Jusqu'à ce que Microsoft résoudre ce problème, voici un travail autour de:

Créez votre propre méthode d'extension qui utilise la méthode CopyToDataTable s'il y a DataRows, s'il n'y a pas, il retourne un DataTable vide.

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

Je pense que cela pourrait être légèrement amélioré pour utiliser '! Source.Any()' au lieu de 'Source.Count() == 0'. 'Any' s'arrêtera dès qu'il trouvera des résultats. – row1

+0

Beaucoup plus que légèrement –

+2

Ce n'est pas un bug; le comportement est très conçu et délibéré.L'une des premières choses que 'CopyToDataTable' fait est saisir une ligne, trouver la table sous-jacente, et copier les colonnes dans votre nouveau' DataTable'. Votre solution de contournement crée un 'DataTable' vide sans colonnes. Vous pouvez vous en sortir avec un DataSource (il ne regardera pas la table s'il n'a pas de ligne), mais dans d'autres cas, vous ne pouvez pas le faire. – Brian

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

.AsDataView().ToTable() retourne une table vide avec la même structure que someDataTable s'il y a maintenant des lignes de retour .Where()

+0

cool, je vais essayer, vince – andy

+0

un problème que je vois avec votre extension personnalisée est la vérification de .Count. Si je ne me trompe pas, .Count force la lecture de l'énumération entière. Par conséquent, si votre compte est dit, 1000, alors vous lisez toute l'énumération puis appelez CopyToDataTable() qui force probablement une autre lecture. Avez-vous envisagé de vérifier si .GetEnumerator(). MoveNext() == true? Si cela est vrai, l'énumération comporte au moins une ligne, et c'est tout ce qui vous préoccupe, pas le nombre. – Vince

+0

bon point vince, vous avez tout à fait raison. Je vais le mettre à jour, à votre santé! – andy

1

Je suis tombé sur ce problème aujourd'hui et élaboré un workaround si ça aide.

Désolé, mais le blog est en C#, mais je viens d'utiliser un IEnumerable sur la variable LINQ et vérifiez .Current pour voir si elle était retourné toutes les lignes.

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 
} 
Questions connexes