write multiple fields csvwriter create crear columns and c# linq datatable

c# - multiple - DataTable Union



linq c# group by and select columns c# (2)

El problema aquí es que Linq no sabe que quiere comparar el Name . En cambio, hace lo que hace para todos los tipos de objetos, compara el hash, que es diferente para dos instancias diferentes.

Lo que necesita hacer es decirle al método de la Unión cómo comparar dos elementos. Puede hacerlo creando un IEqualityComparer personalizado que compare dos filas de datos de la forma que desee.

Aquí hay una implementación de ejemplo:

class CustomComparer : IEqualityComparer<DataRow> { #region IEqualityComparer<DataRow> Members public bool Equals(DataRow x, DataRow y) { return ((string)x["Name"]).Equals((string)y["Name"]); } public int GetHashCode(DataRow obj) { return ((string)obj["Name"]).GetHashCode(); } #endregion }

Cuando llame a Union , deberá pasar una instancia de este comparador:

var comparer = new CustomComparer(); DataTable dtUnion = dt1.AsEnumerable() .Union(dt2.AsEnumerable(), comparer).CopyToDataTable<DataRow>();

Vea aqui para mas informacion:
http://msdn.microsoft.com/en-us/library/bb358407.aspx

Un consejo:
Linq es mejor con clases de datos personalizadas, que no es DataRow . Lo mejor es tener una propiedad de Nombre real en la clase, solo entonces Linq realmente puede brillar.
Si no necesita la flexibilidad del esquema dinámico, debe mantenerse alejado de DataTable e implementar clases personalizadas que se parezcan exactamente a lo que necesita, ya que DataTable es extremadamente lento y lento.

¿Podría verificar lo siguiente?

Necesito la unión de esto, pero devuelve 6 registros en lugar de 5 (porque "Amir" aparece dos veces)

DataTable dt1 = new DataTable(); dt1.Columns.Add(new DataColumn("Name")); dt1.Rows.Add(dt1.NewRow()["Name"] = "Imran"); dt1.Rows.Add(dt1.NewRow()["Name"] = "Amir"); dt1.Rows.Add(dt1.NewRow()["Name"] = "Asif"); DataTable dt2 = new DataTable(); dt2.Columns.Add(new DataColumn("Name")); dt2.Rows.Add(dt2.NewRow()["Name"] = "Tandulkar"); dt2.Rows.Add(dt2.NewRow()["Name"] = "Amir"); dt2.Rows.Add(dt2.NewRow()["Name"] = "Sheqwag"); DataTable dtUnion = dt1.AsEnumerable() .Union(dt2.AsEnumerable()).CopyToDataTable<DataRow>();


Si los esquemas de DataTables son los mismos, puede usar el DataRowComparer.Default existente, así:

DataTable dtUnion = dt1.AsEnumerable().Union(dt2.AsEnumerable()).Distinct(DataRowComparer.Default).CopyToDataTable<DataRow>();

Y la función Agregar es muy útil cuando necesita unir más de 2 tablas, por ejemplo:

// Create a table "template" DataTable dt = new DataTable(); dt.Columns.Add(new DataColumn("Name")); // Create a List of DataTables and add 3 identical tables List<DataTable> dtList = new List<DataTable>(); dtList.AddRange(new List<DataTable>() { dt.Clone(), dt.Clone(), dt.Clone()}); // Populate the 3 clones with some data dtList[0].Rows.Add("Imran"); dtList[0].Rows.Add("Amir"); dtList[0].Rows.Add("Asif"); dtList[1].Rows.Add("Tandulkar"); dtList[1].Rows.Add("Amir"); dtList[1].Rows.Add("Sheqwag"); dtList[2].Rows.Add("John"); dtList[2].Rows.Add("Sheqwag"); dtList[2].Rows.Add("Mike"); // Union the 3 clones into a single DataTable containing only distinct rows DataTable dtUnion = dtList .Select(d => d.Select().AsEnumerable()) .Aggregate((current, next) => current.Union(next)) .Distinct(DataRowComparer.Default) .CopyToDataTable<DataRow>();