将数据集转换为列表

Posted

技术标签:

【中文标题】将数据集转换为列表【英文标题】:Convert DataSet to List 【发布时间】:2013-06-11 00:40:30 【问题描述】:

这是我的 C# 代码

Employee objEmp = new Employee();
List<Employee> empList = new List<Employee>();
foreach (DataRow dr in ds.Tables[0].Rows)

    empList.Add(new Employee  Name = Convert.ToString(dr["Name"]), Age = Convert.ToInt32(dr["Age"]) );

它使用循环从数据集创建列表。是否有任何直接方法或更短的方法或一行代码

【问题讨论】:

为什么需要它在一行?当前的多行表格是否同样易于阅读? @JensKloster 知道它是否可以写成一行有什么害处:) 【参考方案1】:

这是将DataTable转换为对象列表的扩展方法:

    public static class Extensions
    
        public static List<T> ToList<T>(this DataTable table) where T : new()
        
            IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
            List<T> result = new List<T>();

            foreach (var row in table.Rows)
            
                var item = CreateItemFromRow<T>((DataRow)row, properties);
                result.Add(item);
            

            return result;
        

        private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
        
            T item = new T();
            foreach (var property in properties)
            
                if (property.PropertyType == typeof(System.DayOfWeek))
                
                    DayOfWeek day = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), row[property.Name].ToString());
                    property.SetValue(item,day,null);
                
                else
                
                    if(row[property.Name] == DBNull.Value)
                        property.SetValue(item, null, null);
                    else
                    
                        if (Nullable.GetUnderlyingType(property.PropertyType) != null)
                        
                            //nullable
                            object convertedValue = null;
                            try
                            
                                convertedValue = System.Convert.ChangeType(row[property.Name], Nullable.GetUnderlyingType(property.PropertyType));
                            
                            catch (Exception ex)
                            
                            
                            property.SetValue(item, convertedValue, null);
                        
                        else
                            property.SetValue(item, row[property.Name], null);
                    
                
            
            return item;
        
    

用法:

List<Employee> lst = ds.Tables[0].ToList<Employee>();

@itay.b 代码解释: 我们首先使用反射从类 T 中读取所有属性名称 然后我们遍历数据表中的所有行并创建 T 的新对象, 然后我们使用反射设置新创建对象的属性。

属性值是从行的匹配列单元格中选取的。

PS:类属性名和表列名必须相同

【讨论】:

喜欢这个,很好的答案,也是泛型的一个很好的例子。 我可以看到你解释了如何转换系统定义的枚举类型,你能解释一下我如何转换像性别这样的代码中定义的枚举类型吗?谢谢 请问为什么在CreateItemFromRow中,你首先要检查属性的类型是否等于typeof(System.DayOfWeek)?调用property.SetValue(item, row[property.Name], null) 会导致异常吗? 是的@StevenVolckaert【参考方案2】:

试试这样的:

var empList = ds.Tables[0].AsEnumerable()
    .Select(dataRow => new Employee
    
        Name = dataRow.Field<string>("Name")
    ).ToList();

【讨论】:

这是我试过的 --- var empList = ds.Tables[0].AsEnumerable().Select(dataRow => new Employee Name = dataRow.Field("Name" ), Age = dataRow.Field("Age") ).ToList();说“指定的演员阵容无效” 如果您收到错误“指定的演员表无效”。尝试将 ToList 放在 AsEnumerable 之后。解决方案来自:***.com/questions/22159695/… var ProTLData = ds.Tables[0].AsEnumerable().ToList().Select(s => new IssueViewModel ProjectId = s.Field("ProjectId"), RoleId = s.Field("RoleId"), UserId = s.Field("UserId"), UserName = s.Field("UserName") ); custData.IssueList = ProTLData.ToList();这不会生成指定的转换错误,但是当我在 custData.IssueList 中分配时,它会生成相同的错误【参考方案3】:

我无法得到 Nitin Sawant 的工作答案,但我能够修改他的代码来为我工作。本质上,我需要使用 GetRuntimeFields 而不是 GetProperties。这是我最终得到的结果:

public static class Extensions

    public static List<T> ToList<T>(this DataTable table) where T : new()
    
        IList<FieldInfo> fields = typeof(T).GetRuntimeFields().ToList();
        List<T> result = new List<T>();
        if (row.Table.Columns.Contains(field.Name))
        
            foreach (var row in table.Rows)
            
                var item = CreateItemFromRow<T>((DataRow)row, fields);
                result.Add(item);
            
        

        return result;
    

    private static T CreateItemFromRow<T>(DataRow row, IList<FieldInfo> fields) where T : new()
    
        T item = new T();

        foreach (var field in fields)
        
            if (row[field.Name] == DBNull.Value)
                field.SetValue(item, null);
            else
                field.SetValue(item, row[field.Name]);
        
        return item;
    

【讨论】:

ToList 方法中使用的 if 中的行变量声明在哪里? 您忘记了List&lt;T&gt; result = new List&lt;T&gt;(); 行后的foreach 循环【参考方案4】:
 List<GSTEntity.gst_jobwork_to_mfgmaster> ListToGetJwToMfData = new List<GSTEntity.gst_jobwork_to_mfgmaster>();
            DataSet getJwtMF = new DataSet();
            getJwtMF = objgst_jobwork_to_mfgmaster_BLL.GetDataJobWorkToMfg(AssesseeId, PremiseId,  Fyear,  MonthId, out webex);
            if(getJwtMF.Tables["gst_jobwork_to_mfgmaster"] != null)
            

                ListToGetJwToMfData = (from master in getJwtMF.Tables["gst_jobwork_to_mfgmaster"].AsEnumerable() select new GSTEntity.gst_jobwork_to_mfgmaster  Partygstin = master.Field<string>("Partygstin"), Partystate =
                                       master.Field<string>("Partystate"), NatureOfTransaction = master.Field<string>("NatureOfTransaction"), ChallanNo = master.Field<string>("ChallanNo"), ChallanDate=master.Field<int>("ChallanDate"),  OtherJW_ChallanNo=master.Field<string>("OtherJW_ChallanNo"),   OtherJW_ChallanDate = master.Field<int>("OtherJW_ChallanDate"),
                    OtherJW_GSTIN=master.Field<string>("OtherJW_GSTIN"),
                    OtherJW_State = master.Field<string>("OtherJW_State"),
                    InvoiceNo = master.Field<string>("InvoiceNo"),
                    InvoiceDate=master.Field<int>("InvoiceDate"),
                    Description =master.Field<string>("Description"),
                    UQC= master.Field<string>("UQC"),
                    qty=master.Field<decimal>("qty"),
                    TaxValue=master.Field<decimal>("TaxValue"),
                    Id=master.Field<int>("Id")                        

                ).ToList();

【讨论】:

请在上述源代码中添加一些解释。【参考方案5】:

添加一个名为“Helper”的新类并将该类的属性更改为“public static”

public static class Helper

    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);
                        propertyInfo.SetValue(obj, Convert.ChangeType(row[prop.Name], propertyInfo.PropertyType), null);
                    
                    catch
                    
                        continue;
                    
                

                list.Add(obj);
            

            return list;
        
        catch
        
            return null;
        
    

并在您的代码中访问此类,如下所示

 DataTable dtt = dsCallList.Tables[0];
 List<CallAssignment> lstCallAssignement = dtt.DataTableToList<CallAssignment>();

【讨论】:

【参考方案6】:

使用下面的代码:

using Newtonsoft.Json;
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(ds.Tables[0]);

【讨论】:

最好的方法。 是的,对我有用。谢谢【参考方案7】:
                DataSet ds = new DataSet();
                ds = obj.getXmlData();// get the multiple table in dataset.

                Employee objEmp = new Employee ();// create the object of class Employee 
                List<Employee > empList = new List<Employee >();
                int table = Convert.ToInt32(ds.Tables.Count);// count the number of table in dataset
                for (int i = 1; i < table; i++)// set the table value in list one by one
                
                    foreach (DataRow dr in ds.Tables[i].Rows)
                    
                        empList.Add(new Employee  Title1 = Convert.ToString(dr["Title"]), Hosting1 = Convert.ToString(dr["Hosting"]), Startdate1 = Convert.ToString(dr["Startdate"]), ExpDate1 = Convert.ToString(dr["ExpDate"]) );
                    
                
                dataGridView1.DataSource = empList;

【讨论】:

【参考方案8】:

用来自存储的 proc 命令的数据填充数据集

DbDataAdapter adapter = DbProviderFactories.GetFactory(cmd.Connection).CreateDataAdapter();
adapter.SelectCommand = cmd;
DataSet ds = new DataSet();
adapter.Fill(ds);

获取架构,

string s = ds.GetXmlSchema();

将其保存到文件中,例如:datasetSchema.xsd。为 Schema 生成 C# 类:(在 VS 命令提示符处)

xsd datasetSchema.xsd /c

现在,当您需要将 DataSet 数据转换为可以反序列化的类时(生成的根类的默认名称是 NewDataSet):

public static T Create<T>(string xml)

    XmlSerializer serializer = new XmlSerializer(typeof(T));
    using (StringReader reader = new StringReader(xml))
    
        T t = (T)serializer.Deserialize(reader);

        reader.Close();
        return t;
    


var xml = ds.GetXml();
var dataSetObjects = Create<NewDataSet>(xml);

【讨论】:

+1。这让我更接近my own XML serialization/deserialization question 的答案。【参考方案9】:

试试这个....根据您的需要修改代码。

      List<Employee> target = dt.AsEnumerable()
      .Select(row => new Employee
      
        Name = row.Field<string?>(0).GetValueOrDefault(),
        Age= row.Field<int>(1)
      ).ToList();

【讨论】:

只是一个小注释,但字符串已经可以为空,用字符串没有用吗? 我找不到 ToList() 方法,它没有出现 @NewTech 使用 - 使用 System.Linq;【参考方案10】:
var myData = ds.Tables[0].AsEnumerable().Select(r => new Employee 
    Name = r.Field<string>("Name"),
    Age = r.Field<int>("Age")
);
var list = myData.ToList(); // For if you really need a List and not IEnumerable

【讨论】:

【参考方案11】:

试试上面的方法,任何列表类型都可以运行。

  public DataTable ListToDataTable<T>(IList<T> data)
    
        PropertyDescriptorCollection props =
            TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        for (int i = 0; i < props.Count; i++)
        
            PropertyDescriptor prop = props[i];
            table.Columns.Add(prop.Name, prop.PropertyType);
        
        object[] values = new object[props.Count];
        foreach (T item in data)
        
            for (int i = 0; i < values.Length; i++)
            
                values[i] = props[i].GetValue(item);
            
            table.Rows.Add(values);
        
        return table;
    

【讨论】:

以上是关于将数据集转换为列表的主要内容,如果未能解决你的问题,请参考以下文章

Javascript: 将数值列表转换为对象集

在 C# 中将通用列表转换为数据集 [关闭]

Javascript:将值列表转换为对象集

PyTorch 数据集:将整个数据集转换为 NumPy

将文本数据集转换为数字数据集

将时间序列数据集转换为监督学习数据集