2009-06-26 10 views
-1

J'ai deux datatables. DataTable dtRequired et DataTable dtResult.différence entre 2 données

Je souhaite générer une base de données contenant des lignes qui n'étaient pas présentes dans dtResponse mais qui ont été trouvées dans dtRequired.

Approche 1 Nous utilisons l'algorithme spécifié à l'adresse suivante http://weblogs.sqlteam.com/davidm/archive/2004/01/19/739.aspx. Et cet algorithme a été considéré comme l'un des plus lents de notre profilage.

Approche 2 Donc, j'ai essayé de remplacer l'algo ci-dessus par quelque chose qui est décrit ci-dessous. dtRequired est indexé sur les colonnes I m en utilisant ci-dessous à Recherchez la ligne.

if (dtResult.Rows.Count > 0) 
    { 
     lock (dtResult) 
     { 
      DataRow rowfound = null; 
      for (int i = 0; i < dtResult.Rows.Count; i++) 
      { 
       DataRow row = dtResult.Rows[i]; 
       rowfound = dtRequired.Rows.Find(new object[] { row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8] }); 
       if (rowfound != null) 
       { 
        dtRequired.Rows.Remove(rowfound); 
       } 
      }       
     } 
    } 

La pièce ci-dessus est cependant plus long que le temps pris par Approche 1. L'approche 2 prend ~ 3 secondes pour dtResult avec 1250 lignes et dtRequired avec 4500 lignes.

Quelque chose ne va pas avec l'approche que j'ai mentionnée ci-dessus? Y a-t-il une meilleure approche pour y parvenir?

+1

Si je peux demander, pourquoi faites-vous cela en utilisant dataTable? Cela ne peut-il pas être fait au backend? – shahkalpesh

+0

Non. Le datatable source est utilisé pour former une structure de données compacte qui est envoyée au Webservice. Webservice interprète ces données en conséquence, puis renvoie l'ensemble de données. –

+1

Les deux tables ont-elles une colonne unique pouvant être triée? Si c'est le cas; vous pouvez trier les deux en premier, puis utiliser un algorithme de fusion (voir http: //en.wikipedia.org/wiki/Merge_algorithm) pour avancer chaque ligne de la table en cours tandis qu'elle est derrière l'autre, en insérant les lignes manquantes dans une nouvelle table. –

Répondre

1

Ceci est une link vers une page MSDN qui utilise LINQ to DataSet pour obtenir les lignes qui apparaissent dans les deux datatables. Cet exemple utilise Intersect. Je pense que vous pouvez le modifier en utilisant à l'exception de à la place. Je ne sais pas si la performance sera meilleure ou non.

+0

Je suis sur .NET 2.0. –

0
private IEnumerator<object[]> GetEnumerator(DataTable dtRequired, DataTable dtResponse) 
{ 
    foreach(DataRow row in dtResponse.Rows) 
    { 
     // use the columns of the primary key below 
     if(dtResult.Rows.Contains(new object[] { row[0], row[2], row[4] })) 
      continue; 
     else 
      yield return row.ItemArray; 

    } 
} 

private void GetComplement(DataTable dtRequired, DataTable dtResponse, out DataTable dtResult) 
{ 
    DataTable dtResult = dtRequired.Clone(); 

    foreach(object[] items in GetEnumerator(dtRequired, dtResponse)) 
    { 
     dtResult.Rows.Add(items); 
    } 

    return; 
} 
+0

Il peut y avoir une fermeture syntaxique à effectuer avec IEnumerator par rapport à IEnumerable . – maxwellb

0
  1. Vous avez dit que votre méthode Find() en boucle est moins efficace que l'approche 1 http://weblogs.sqlteam.com/davidm/archive/2004/01/19/739.aspx.

  2. J'ai vu des gens parler d'ADO.NET 3.5 et de LINQ, en supposant que vous ayez un LINQ de production ou que vous utilisiez une méthode itérative pour remplir un conteneur générique. Je me demande si l'utilisation créative d'un HashTable serait plus rapide, informatiquement (monde réel, pas de théorie). Dans le cas de Diff (tbl1, tb2), remplissez simplement le hachage avec tbl2 puis ajoutez itérativement les membres tbl1. Pour chaque succès, ajoutez également une copie du membre au tableau de sortie (différence) à afficher/renvoyer. Pour chaque échec, évidemment, il existe déjà, donc ne pas sortir/retourner cette valeur. Faites-moi savoir, je vais retravailler mon code si vous confirmez que 3 est le plus rapide.

Je compare une collection DirectoryServices.FindAll() à un SqlDataReader() et LINQ à Active Directory est en version bêta tierce, je suppose. J'ai donc besoin d'une méthode approuvée 'production' ici aussi efficace que possible @ 15 000 objets.

Questions connexes