首页 文章

如何将DataTable转换为通用列表?

提问于
浏览
156

目前,我正在使用:

DataTable dt = CreateDataTableInSomeWay();

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

有更好的/神奇的方式吗?

21 回答

  • 9
    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();
    
  • 6

    再次使用3.5你可以这样做:

    dt.Select().ToList()
    

    BRGDS

  • 3

    如果您使用的是.NET 3.5,则可以使用DataTableExtensions.AsEnumerable(扩展方法)然后如果您确实需要 List<DataRow> 而不仅仅是 IEnumerable<DataRow> ,则可以调用Enumerable.ToList

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

    要么

    using System.Linq;
    ...
    List<DataRow> list = dt.AsEnumerable().ToList();
    
  • 11
    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();
    
  • 3

    使用C#3.0和System.Data.DataSetExtensions.dll,

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

    你可以用

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

    dt.Select() 将返回表中的所有行,作为数据行数组, List 构造函数接受该对象数组作为参数,以便最初填充列表 .

  • 30

    如果您只想要返回“ID”int字段中的值列表,您可以使用...

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

    您可以创建扩展功能:

    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>();
    
  • 244

    我已经从这个答案添加了一些修改(https://stackoverflow.com/a/24588210/4489664),因为对于可以为空的类型,它将返回异常

    public static List<T> DataTableToList<T>(this DataTable table) where T: new()
    {
        List<T> list = new List<T>();
        var typeProperties = typeof(T).GetProperties().Select(propertyInfo => new
            {
                PropertyInfo = propertyInfo,
                Type = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType
            }).ToList();
    
        foreach (var row in table.Rows.Cast<DataRow>())
        {
            T obj = new T();
            foreach (var typeProperty in typeProperties)
            {
                object value = row[typeProperty.PropertyInfo.Name];
                object safeValue = value == null || DBNull.Value.Equals(value)
                    ? null
                    : Convert.ChangeType(value, typeProperty.Type);
    
                typeProperty.PropertyInfo.SetValue(obj, safeValue, null);
            }
            list.Add(obj);
        }
        return list;
    }
    
  • 34

    一种更“神奇”的方式,不需要.NET 3.5 .

    例如,如果 DBDatatable 返回单个Guids列(SQL中的uniqueidentifier),那么您可以使用:

    Dim gList As New List(Of Guid)
    gList.AddRange(DirectCast(DBDataTable.Select(), IEnumerable(Of Guid)))
    
  • 11
    // 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;
    }
    
  • 0

    DataTable.Select() 并不按照它们在数据表中的顺序给出行 .

    如果顺序很重要,我觉得迭代datarow集合并形成List是正确的方法,或者你也可以使用 DataTable.Select(string filterexpression, string sort) 的重载 .

    但是这个重载可能无法处理SQL提供的所有排序(如逐个...) .

  • 0

    这是一个DataTable扩展方法,它将DataTable转换为通用列表 .

    https://gist.github.com/gaui/a0a615029f1327296cf8

    Usage:

    List<Employee> emp = dtTable.DataTableToList<Employee>();
    
  • 0
    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});
    }
    
  • 6
    /* 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
             */
    

    以下是两个函数,如果我们传递DataTable和用户定义的类 . 然后它将使用DataTable数据返回该类的List .

    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;
            }
    

    此方法将检查字段的数据类型,并将dataTable值转换为该数据类型 .

    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();
        }
    

    要调用上述方法,请使用以下语法:

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

    根据您的要求更改学生 class 名称和学生值 . 在这种情况下,DataTable列的名称和类属性名称应该相同,否则此函数将无法正常工作 .

  • 2

    This worked for me: 至少需要.Net Framework 3.5,下面的代码显示DataRow转向Generic.IEnumerable,comboBox1已用于更好的说明 .

    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;
    
  • 0

    使用 System.Data 命名空间然后你会得到 .AsEnumerable() .

  • 0

    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", "Jame@hotmail.com", DateTime.Now.ToString());
        table.Rows.Add(50, "luci", "luci@hotmail.com", DateTime.Now.ToString());
        table.Rows.Add(10, "Andrey", "Andrey@hotmail.com", DateTime.Now.ToString());
        table.Rows.Add(21, "Michael", "Michael@hotmail.com", DateTime.Now.ToString());
        table.Rows.Add(100, "Steven", "Steven@hotmail.com", 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>
    
  • 0

    我们可以使用通用方法将 DataTable 转换为 List ,而不是手动将 DataTable 转换为 List .

    注意: DataTableColumnNameTypePropertyName 应该相同 .

    调用以下方法:

    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;
        }
    }
    
  • 61

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

    查看此库以进行转换,您将在此处找到所有类型的转换,例如: -

    • DataTable到GenericList

    • DataTable的通用类型

    • Json到DataTable,通用列表,通用类型

    • DataTable到Json

  • 1

    您可以使用类似于通用列表的数据通用方法

    public static List<T> DataTableToList<T>(this DataTable table) where T : class, new()
    {
        try
        {
            List<T> list = new List<T>();
    
            foreach (var row in table.AsEnumerable())
            {
                T obj = new T();
    
                foreach (var prop in obj.GetType().GetProperties())
                {
                    try
                    {
                        PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);
                        if (propertyInfo.PropertyType.IsEnum)
                        {
                            propertyInfo.SetValue(obj, Enum.Parse(propertyInfo.PropertyType, row[prop.Name].ToString()));
                        }
                        else
                        {
                            propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
                        }                          
                    }
                    catch
                    {
                        continue;
                    }
                }
    
                list.Add(obj);
            }
    
            return list;
        }
        catch
        {
            return null;
        }
    }
    

相关问题