De momento se me ocurren dos soluciones: LINQ y una técnica usa el DefaultView . Sería cuestión de probar cual es más eficiente ya que las dos logran el mismo resultado. Hagamos entonces las prueba.
Primero nos hacemos un proyecto consola y nos creamos un DataTable con unas tres columnas; lo llenamos con valores aleatorios para simular las filas. Esta prueba la realizaremos con 200 mil registros:
//Para llevar el control del tiempo de ejecucion Stopwatch st = new Stopwatch(); //Creamos la tabla DataTable dt = new DataTable(); dt.Columns.Add("Codigo", typeof(int)); dt.Columns.Add("Descripcion", typeof(string)); dt.Columns.Add("Ubicacion", typeof(int)); //La llenamos con valores aleatorios Random x = new Random(); for (decimal i=0; i < 200000; i++) { int X = x.Next(1,100); int Y = x.Next(1,10); int Z = x.Next(1,1000); dt.Rows.Add(X, Y.ToString(), Z); }De esta tabla voy a querer las columnas Codigo y Descripcion pero sin registros repetidos. Completamos esta tarea aplicando el distinct según LINQ,
st.Start(); //Linq para extraer las columnas deseadas sin que se repitan var distinctRows = (from DataRow dRow in dt.Rows select new { col_id = dRow["Codigo"], col_desc = dRow["Descripcion"] }).Distinct(); st.Stop(); //Mostramos la cantidad de registros únicos encontrados y el tiempo de ejecución string tiempoCarga = (st.ElapsedMilliseconds / 1000).ToString(); Console.WriteLine("Registros {0} cargados en {1} segundos unsando LinQ.",distinctRows.Count().ToString(), tiempoCarga);
Ahora, podemos obtener el mismo resultado usando el DefaultView del DataTable y vaciandolo en un nuevo DataTable:
st.Reset();//Reseteamos el contador de tiempo st.Start(); DataTable dt2 = dt.DefaultView.ToTable(true, "Codigo", "Descripcion"); st.Stop(); //Mostramos la cantidad de registros únicos y el tiempo de ejecución tiempoCarga = (st.ElapsedMilliseconds / 1000).ToString(); Console.WriteLine("Registros {0} cargados en {1} segundos unsando DefaultView.ToTable.",dt2.Rows.Count.ToString(), tiempoCarga); Console.ReadLine();
Ahora procedemos a ejecutar la prueba y obtener los resultados:
Como podemos observar ambos llegan a la misma cantidad de registros únicos, pero los tiempos de respuesta difieren significativamente uno de otro. Mientras el Distinct de LINQ es prácticamente instantáneo, usando la técnica del DefaultView consume en promedio 6 segundos. Ganador absoluto de la prueba LINQ!
Solo como referencia final, la forma en la que se recorren los registros obtenidos por medio del LINQ es la siguiente:
double count = 0; foreach (var row in distinctRows) { count++; Console.WriteLine("{0} - ID:{0} Descripcion {1} ", count.ToString(), row.col_id.ToString(), row.col_desc.ToString()); }
Interesante!