我正在使用ExcelDataReader将Excel文件导入到数据集。Excel表示例:


//ID     Name     Display Order    Active
//1      John          1             1



IDDisplayOrderActive列读取为double,因此我必须将它们分别转换为longintbool类型。我需要从DataSet的DataTable中创建一个类型为Category的列表。

此代码性能良好吗?有什么建议可以将DataTable更快地转换为类列表吗?

评论

由于双重舍入问题和相等性比较,我可能会将最后一行重写为IsActive = dr.Field (“ Active”)> 0(因为比较已经评估为true或false,因此您的三元数是不必要的)。 />
谢谢杰西。还有什么需要改进的吗?

我得说,这看起来非常简洁明了。

您可以直接通过名称访问DataRow字段:dr [“ ID”],dr [“ Name”]等。它们是对象类型,但是Convert.To ____()函数可以处理这些。

#1 楼

我为DataTable创建了扩展方法,将其转换为List<T>

public static class Helper
{
    /// <summary>
    /// Converts a DataTable to a list with generic objects
    /// </summary>
    /// <typeparam name="T">Generic object</typeparam>
    /// <param name="table">DataTable</param>
    /// <returns>List with generic objects</returns>
    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;
        }
    }
}


示例:

评论


\ $ \ begingroup \ $
你是救命稻草!我什至不知道Convert.ChangeType一直存在到今天。这比我尝试在目标类型上调用TryParse所做的要简单得多。而且,这还可以处理DataTable中的DBNull值。 10/10!
\ $ \ endgroup \ $
–克鲁梅尔兹
2015年1月5日,10:50

\ $ \ begingroup \ $
有趣的代码,我只是想知道与非通用代码相比,它的性能如何?
\ $ \ endgroup \ $
–小睡
15年1月8日在7:55

\ $ \ begingroup \ $
您可能要考虑一个很好的答案的更新是仅更新可编辑属性,以减少抛出的所有异常。以下代码将适当地更新您的代码:foreach(obj.GetType()。GetProperties()**。Where(p => p.CanWrite)**)中的var prop)
\ $ \ endgroup \ $
– GregTank
2015年4月28日在21:54



\ $ \ begingroup \ $
@Nap由于反射,此代码的性能将大大降低。具有出色性能的优雅解决方案。
\ $ \ endgroup \ $
–Zer0
2015年5月9日10:13



\ $ \ begingroup \ $
注意:建议将方法重命名为ToList而不是DataTableToList,因为它已经是DataTable的扩展方法。并且还将匹配ToString,ToChar等的标准约定。
\ $ \ endgroup \ $
– BornToCode
2015年11月26日在16:39



#2 楼

只需进行一些重构和一点缓存,就可以在Gaui的答案中失去一些反射上的缺陷:

评论


\ $ \ begingroup \ $
可能要检查属性的set方法或更改以对row.Table.Columns中的列进行迭代,以便支持只读属性
\ $ \ endgroup \ $
–挡风板
15年8月24日在20:45

\ $ \ begingroup \ $
@moarboilerplate易于添加。
\ $ \ endgroup \ $
–Jesse C. Slicer
15年8月24日在20:57

\ $ \ begingroup \ $
我真的很喜欢您的解决方案,它可以正常工作,但是由于有DateTime,我收到了错误消息?和诠释?类中的属性,我收到错误消息,说我无法从System.DateTIme强制转换为System.Nullable。这个可以解决吗?
\ $ \ endgroup \ $
– Misiu
16年8月26日在11:41

\ $ \ begingroup \ $
我在这里找到了简单的解决方案:stackoverflow.com/a/3531824/965722,所以也许您可以将其添加到您的代码中。这将对像我这样的其他发现者有所帮助。
\ $ \ endgroup \ $
– Misiu
16年8月26日在11:46

\ $ \ begingroup \ $
@ JesseC.Slicer我将它与其他库提供的大型数据表结合使用(我无法更改)。您的解决方案是使用反射。我找到了许多有关表达式树和lambda的文章,所以我想知道是否有可能将您的代码更改为使用这些代码而不是反射代码。
\ $ \ endgroup \ $
– Misiu
16年9月2日在8:24