query parse example enumerablerowcollection convert consulta c# generics datatable

example - parse list to datatable c#



¿Cómo se convierte una DataTable en una lista genérica? (20)

Actualmente, estoy usando:

DataTable dt = CreateDataTableInSomeWay(); List<DataRow> list = new List<DataRow>(); foreach (DataRow dr in dt.Rows) { list.Add(dr); }

¿Hay una forma mejor / mágica?



Con C # 3.0 y System.Data.DataSetExtensions.dll,

List<DataRow> rows = table.Rows.Cast<DataRow>().ToList();


Modifiqué un código de esta respuesta ( https://.com/a/24588210/4489664 ) porque cuando usaba DateTime con nulos en mi clase, devolvía el error

public static List<T> DataTableToList<T>(this DataTable table) where T : class, new() { try { T tempT = new T(); var tType = tempT.GetType(); List<T> list = new List<T>(); foreach (var row in table.Rows.Cast<DataRow>()) { T obj = new T(); foreach (var prop in obj.GetType().GetProperties()) { var propertyInfo = tType.GetProperty(prop.Name); var rowValue = row[prop.Name]; var t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; try { object safeValue = (rowValue == null || DBNull.Value.Equals(rowValue)) ? null : Convert.ChangeType(rowValue, t); propertyInfo.SetValue(obj, safeValue, null); } catch (Exception ex) {//this write exception to my logger _logger.Error(ex.Message); } } list.Add(obj); } return list; } catch { return null; } }


Nuevamente, usando 3.5 puedes hacerlo como:

dt.Select().ToList()

BRGDS


Podemos usar un Método genérico para convertir DataTable a List lugar de convertir manualmente una DataTable a List .

Nota: ColumnName DataTable y ColumnName Type deben ser iguales.

Llame al siguiente método:

long result = Utilities.ConvertTo<Student>(dt ,out listStudent); // Generic Method public class Utilities { public static long ConvertTo<T>(DataTable table, out List<T> entity) { long returnCode = -1; entity = null; if (table == null) { return -1; } try { entity = ConvertTo<T>(table.Rows); returnCode = 0; } catch (Exception ex) { returnCode = 1000; } return returnCode; } static List<T> ConvertTo<T>(DataRowCollection rows) { List<T> list = null; if (rows != null) { list = new List<T>(); foreach (DataRow row in rows) { T item = CreateItem<T>(row); list.Add(item); } } return list; } static T CreateItem<T>(DataRow row) { string str = string.Empty; string strObj = string.Empty; T obj = default(T); if (row != null) { obj = Activator.CreateInstance<T>(); strObj = obj.ToString(); NameValueCollection objDictionary = new NameValueCollection(); foreach (DataColumn column in row.Table.Columns) { PropertyInfo prop = obj.GetType().GetProperty(column.ColumnName); if (prop != null) { str = column.ColumnName; try { objDictionary.Add(str, row[str].ToString()); object value = row[column.ColumnName]; Type vType = obj.GetType(); if (value == DBNull.Value) { if (vType == typeof(int) || vType == typeof(Int16) || vType == typeof(Int32) || vType == typeof(Int64) || vType == typeof(decimal) || vType == typeof(float) || vType == typeof(double)) { value = 0; } else if (vType == typeof(bool)) { value = false; } else if (vType == typeof(DateTime)) { value = DateTime.MaxValue; } else { value = null; } prop.SetValue(obj, value, null); } else { prop.SetValue(obj, value, null); } } catch(Exception ex) { } } } PropertyInfo ActionProp = obj.GetType().GetProperty("ActionTemplateValue"); if (ActionProp != null) { object ActionValue = objDictionary; ActionProp.SetValue(obj, ActionValue, null); } } return obj; } }


Podrías usar

List<DataRow> list = new List<DataRow>(dt.Select());

dt.Select() devolverá todas las filas en su tabla, como una matriz de datarows, y el constructor List acepta esa matriz de objetos como un argumento para llenar su lista inicialmente.


Puede crear una función de extensión como:

public static List<T> ToListof<T>(this DataTable dt) { const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; var columnNames = dt.Columns.Cast<DataColumn>() .Select(c => c.ColumnName) .ToList(); var objectProperties = typeof(T).GetProperties(flags); var targetList = dt.AsEnumerable().Select(dataRow => { var instanceOfT = Activator.CreateInstance<T>(); foreach (var properties in objectProperties.Where(properties => columnNames.Contains(properties.Name) && dataRow[properties.Name] != DBNull.Value)) { properties.SetValue(instanceOfT, dataRow[properties.Name], null); } return instanceOfT; }).ToList(); return targetList; } var output = yourDataInstance.ToListof<targetModelType>();


Si solo desea que se devuelva una lista de valores del campo int "ID", podría usar ...

List<int> ids = (from row in dt.AsEnumerable() select Convert.ToInt32(row["ID"])).ToList();


Si usa .NET 3.5, puede usar DataTableExtensions.AsEnumerable (un método de extensión) y luego, si realmente necesita una List<DataRow> lugar de solo IEnumerable<DataRow> , puede llamar a Enumerable.ToList :

IEnumerable<DataRow> sequence = dt.AsEnumerable();

o

using System.Linq; ... List<DataRow> list = dt.AsEnumerable().ToList();


Una forma más ''mágica'', y no necesita .NET 3.5.

Si, por ejemplo, DBDatatable devolviera una sola columna de Guids (uniqueidentifier en SQL), entonces podría usar:

Dim gList As New List(Of Guid) gList.AddRange(DirectCast(DBDataTable.Select(), IEnumerable(Of Guid)))


Use el espacio de nombres System.Data y obtendrá .AsEnumerable() .


Output

public class ModelUser { #region Model private string _username; private string _userpassword; private string _useremail; private int _userid; /// <summary> /// /// </summary> public int userid { set { _userid = value; } get { return _userid; } } /// <summary> /// /// </summary> public string username { set { _username = value; } get { return _username; } } /// <summary> /// /// </summary> public string useremail { set { _useremail = value; } get { return _useremail; } } /// <summary> /// /// </summary> public string userpassword { set { _userpassword = value; } get { return _userpassword; } } #endregion Model } public List<ModelUser> DataTableToList(DataTable dt) { List<ModelUser> modelList = new List<ModelUser>(); int rowsCount = dt.Rows.Count; if (rowsCount > 0) { ModelUser model; for (int n = 0; n < rowsCount; n++) { model = new ModelUser(); model.userid = (int)dt.Rows[n]["userid"]; model.username = dt.Rows[n]["username"].ToString(); model.useremail = dt.Rows[n]["useremail"].ToString(); model.userpassword = dt.Rows[n]["userpassword"].ToString(); modelList.Add(model); } } return modelList; } static DataTable GetTable() { // Here we create a DataTable with four columns. DataTable table = new DataTable(); table.Columns.Add("userid", typeof(int)); table.Columns.Add("username", typeof(string)); table.Columns.Add("useremail", typeof(string)); table.Columns.Add("userpassword", typeof(string)); // Here we add five DataRows. table.Rows.Add(25, "Jame", "[email protected]", DateTime.Now.ToString()); table.Rows.Add(50, "luci", "[email protected]", DateTime.Now.ToString()); table.Rows.Add(10, "Andrey", "[email protected]", DateTime.Now.ToString()); table.Rows.Add(21, "Michael", "[email protected]", DateTime.Now.ToString()); table.Rows.Add(100, "Steven", "[email protected]", DateTime.Now.ToString()); return table; } protected void Page_Load(object sender, EventArgs e) { List<ModelUser> userList = new List<ModelUser>(); DataTable dt = GetTable(); userList = DataTableToList(dt); gv.DataSource = userList; gv.DataBind(); }[enter image description here][1]

</asp:GridView> </div>


https://www.nuget.org/packages/AD.GenericConversion/

Consulte esta biblioteca para la conversión. Encontrará todo tipo de conversiones aquí, como:

  1. DataTable a GenericList
  2. Tipo genérico a DataTable
  3. Json a DataTable, lista genérica, tipo genérico
  4. DataTable a Json

DataTable.Select() no da las Filas en el orden en que estaban presentes en la tabla de datos.

Si el orden es importante, me siento iterando sobre la colección de datarow y formar una lista es el camino correcto o también podría usar la sobrecarga de DataTable.Select(string filterexpression, string sort) .

Pero esta sobrecarga puede no manejar todos los pedidos (como orden por caso ...) que proporciona SQL.


Esto funcionó para mí: Necesito al menos .Net Framework 3.5, el siguiente código muestra DataRow convertido a Generic.IEnumerable, comboBox1 se ha utilizado para una mejor ilustración.

using System.Linq; DataTable dt = new DataTable(); dt = myClass.myMethod(); List<object> list = (from row in dt.AsEnumerable() select (row["name"])).ToList(); comboBox1.DataSource = list;


/* This is a generic method that will convert any type of DataTable to a List * * * Example : List< Student > studentDetails = new List< Student >(); * studentDetails = ConvertDataTable< Student >(dt); * * Warning : In this case the DataTable column''s name and class property name * should be the same otherwise this function will not work properly */

Las siguientes son las dos funciones en las que si pasamos una clase DataTable y una clase definida por el usuario. Luego devolverá la Lista de esa clase con los datos de DataTable.

public static List<T> ConvertDataTable<T>(DataTable dt) { List<T> data = new List<T>(); foreach (DataRow row in dt.Rows) { T item = GetItem<T>(row); data.Add(item); } return data; } private static T GetItem<T>(DataRow dr) { Type temp = typeof(T); T obj = Activator.CreateInstance<T>(); foreach (DataColumn column in dr.Table.Columns) { foreach (PropertyInfo pro in temp.GetProperties()) { //in case you have a enum/GUID datatype in your model //We will check field''s dataType, and convert the value in it. if (pro.Name == column.ColumnName){ try { var convertedValue = GetValueByDataType(pro.PropertyType, dr[column.ColumnName]); pro.SetValue(obj, convertedValue, null); } catch (Exception e) { //ex handle code throw; } //pro.SetValue(obj, dr[column.ColumnName], null); } else continue; } } return obj; }

Este método verificará el tipo de datos del campo y convertirá el valor de la tabla de datos en ese tipo de datos.

private static object GetValueByDataType(Type propertyType, object o) { if (o.ToString() == "null") { return null; } if (propertyType == (typeof(Guid)) || propertyType == typeof(Guid?)) { return Guid.Parse(o.ToString()); } else if (propertyType == typeof(int) || propertyType.IsEnum) { return Convert.ToInt32(o); } else if (propertyType == typeof(decimal) ) { return Convert.ToDecimal(o); } else if (propertyType == typeof(long)) { return Convert.ToInt64(o); } else if (propertyType == typeof(bool) || propertyType == typeof(bool?)) { return Convert.ToBoolean(o); } else if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?)) { return Convert.ToDateTime(o); } return o.ToString(); }

Para llamar al método anterior, use la siguiente sintaxis:

List< Student > studentDetails = new List< Student >(); studentDetails = ConvertDataTable< Student >(dt);

Cambie el nombre de la clase del Estudiante y el valor dt en función de sus requisitos. En este caso, el nombre de la columna DataTable y el nombre de la propiedad de la clase deben ser iguales; de lo contrario, esta función no funcionará correctamente.


// this is better suited for expensive object creation/initialization IEnumerable<Employee> ParseEmployeeTable(DataTable dtEmployees) { var employees = new ConcurrentBag<Employee>(); Parallel.ForEach(dtEmployees.AsEnumerable(), (dr) => { employees.Add(new Employee() { _FirstName = dr["FirstName"].ToString(), _LastName = dr["Last_Name"].ToString() }); }); return employees; }


DataTable dt; // datatable should contains datacolumns with Id,Name List<Employee> employeeList=new List<Employee>(); // Employee should contain EmployeeId, EmployeeName as properties foreach (DataRow dr in dt.Rows) { employeeList.Add(new Employee{EmployeeId=dr.Id,EmplooyeeName=dr.Name}); }


List<Employee> emp = new List<Employee>(); //Maintaining DataTable on ViewState //For Demo only DataTable dt = ViewState["CurrentEmp"] as DataTable; //read data from DataTable //using lamdaexpression emp = (from DataRow row in dt.Rows select new Employee { _FirstName = row["FirstName"].ToString(), _LastName = row["Last_Name"].ToString() }).ToList();


using System.Data; var myEnumerable = myDataTable.AsEnumerable(); List<MyClass> myClassList = (from item in myEnumerable select new MyClass{ MyClassProperty1 = item.Field<string>("DataTableColumnName1"), MyClassProperty2 = item.Field<string>("DataTableColumnName2") }).ToList();