【问题标题】:Need more efficient way to convert Entities to DataTable需要更有效的方式将实体转换为 DataTable
【发布时间】:2012-08-24 18:31:12
【问题描述】:

所以,我有一个将实体转换为 DataTable 的方法。唯一的问题是它非常慢。我确保在 IQueryable 上调用 .ToList() 以使其继续并在将结果处理到 DataTable 之前加载。将 3000 多行加载到内存中几乎不需要任何时间。但是,实时slayer在方法中是在下面的迭代中:

foreach (var index in imgLeaseIndexes)
        {
            DataRow dataRow = dataTable.NewRow();

            dataRow["StateCode"] = index.StateCode;
            dataRow["CountyCode"] = index.CountyCode;
            dataRow["EntryNumber"] = index.EntryNumber;
            dataRow["Volume"] = index.Volume;
            dataRow["Page"] = index.Page;
            dataRow["PageCount"] = index.ImgLocation.PageCount;
            dataRow["CreateDate"] = index.ImgLocation.CreateDate;

            dataTable.Rows.Add(dataRow);
        }

这是完整的方法,值得:

private DataTable buildImgLeaseIndexDataTable(List<ImgLeaseIndex> imgLeaseIndexes)
    {
        var dataTable = new DataTable();
        var dataColumns = new List<DataColumn>(); 
        var tdiReportProperties = 
            new List<string>() { "StateCode", "CountyCode", "EntryNumber", "Volume", "Page", "PageCount", "CreateDate" };

        Type imgLeaseIndexType = imgLeaseIndexes.FirstOrDefault().GetType();
        PropertyInfo[] imgLeaseIndexPropertyInfo = imgLeaseIndexType.GetProperties();

        dataColumns.AddRange(
            (from propertyInfo in imgLeaseIndexPropertyInfo
             where tdiReportProperties.Contains(propertyInfo.Name)
             select new DataColumn()
             {
                 ColumnName = propertyInfo.Name,
                 DataType = (propertyInfo.PropertyType.IsGenericType && 
                    propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) ? 
                    propertyInfo.PropertyType.GetGenericArguments()[0] : propertyInfo.PropertyType
             })
             .ToList());

        Type imgLocationType = imgLeaseIndexes.FirstOrDefault().ImgLocation.GetType();
        PropertyInfo[] imgLocationPropertyInfo = imgLocationType.GetProperties();

        dataColumns.AddRange(
            (from propertyInfo in imgLocationPropertyInfo
             where tdiReportProperties.Contains(propertyInfo.Name)
             select new DataColumn()
             {
                 ColumnName = propertyInfo.Name,
                 DataType = (propertyInfo.PropertyType.IsGenericType &&
                    propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) ?
                    propertyInfo.PropertyType.GetGenericArguments()[0] : propertyInfo.PropertyType
             })
             .ToList());

        dataTable.Columns.AddRange(dataColumns.ToArray());

        foreach (var index in imgLeaseIndexes)
        {
            DataRow dataRow = dataTable.NewRow();

            dataRow["StateCode"] = index.StateCode;
            dataRow["CountyCode"] = index.CountyCode;
            dataRow["EntryNumber"] = index.EntryNumber;
            dataRow["Volume"] = index.Volume;
            dataRow["Page"] = index.Page;
            dataRow["PageCount"] = index.ImgLocation.PageCount;
            dataRow["CreateDate"] = index.ImgLocation.CreateDate;

            dataTable.Rows.Add(dataRow);
        }

        return dataTable;
    }

有没有人知道如何提高效率以及为什么它这么慢?

更新:

根据我目前收到的反馈,我删除了反射并在编译时明确设置数据列,但它仍然很慢。更新后的代码如下所示:

private DataTable buildImgLeaseIndexDataTable(List<ImgLeaseIndex> imgLeaseIndexes)
    {
        var dataTable = new DataTable();

        var stateCodeDataColumn = new DataColumn();
        stateCodeDataColumn.ColumnName = "StateCode";
        stateCodeDataColumn.Caption = "State Code";
        stateCodeDataColumn.DataType = typeof(Int16);
        dataTable.Columns.Add(stateCodeDataColumn);

        var countyCodeDataColumn = new DataColumn();
        countyCodeDataColumn.ColumnName = "CountyCode";
        countyCodeDataColumn.Caption = "County Code";
        countyCodeDataColumn.DataType = typeof(Int16);
        dataTable.Columns.Add(countyCodeDataColumn);

        var entryNumberDataColumn = new DataColumn();
        entryNumberDataColumn.ColumnName = "EntryNumber";
        entryNumberDataColumn.Caption = "Entry Number";
        entryNumberDataColumn.DataType = typeof(string);
        dataTable.Columns.Add(entryNumberDataColumn);

        var volumeDataColumn = new DataColumn();
        volumeDataColumn.ColumnName = "Volume";
        volumeDataColumn.DataType = typeof(string);
        dataTable.Columns.Add(volumeDataColumn);

        var pageDataColumn = new DataColumn();
        pageDataColumn.ColumnName = "Page";
        pageDataColumn.DataType = typeof(string);
        dataTable.Columns.Add(pageDataColumn);

        var pageCountDataColumn = new DataColumn();
        pageCountDataColumn.ColumnName = "PageCount";
        pageCountDataColumn.Caption = "Page Count";
        pageCountDataColumn.DataType = typeof(string);
        dataTable.Columns.Add(pageCountDataColumn);

        var createDateDataColumn = new DataColumn();
        createDateDataColumn.ColumnName = "CreateDate";
        createDateDataColumn.Caption = "Create Date";
        createDateDataColumn.DataType = typeof(DateTime);
        dataTable.Columns.Add(createDateDataColumn);

        foreach (var index in imgLeaseIndexes)
        {
            DataRow dataRow = dataTable.NewRow();

            dataRow["StateCode"] = index.StateCode;
            dataRow["CountyCode"] = index.CountyCode;
            dataRow["EntryNumber"] = index.EntryNumber;
            dataRow["Volume"] = index.Volume;
            dataRow["Page"] = index.Page;
            dataRow["PageCount"] = index.ImgLocation.PageCount;
            dataRow["CreateDate"] = index.ImgLocation.CreateDate;

            dataTable.Rows.Add(dataRow);
        }

        return dataTable;
    }

关于其他可能导致此问题的任何想法?

更新 2:

所以看起来其他人也遇到过这个问题 - 特定于创建和设置 DataRows。我的同事遇到了这个问题:

The DataRow value setter is slow!

我将尝试链接中建议的一些内容。

【问题讨论】:

  • 我相信反射使你的性能下降。
  • 哪一点慢?你分析过代码吗?肯定是foreach吗?
  • 好吧,我并没有真正做到这一点。无论如何,我们的客户使用的是较旧的 Oracle 客户端,因此他们甚至无法处理 EF 的强大功能。我不得不改用强类型数据集。

标签: entity-framework datatable converters


【解决方案1】:

正如 Thiago 在 cmets 中提到的,问题在于反射的使用。

反射部分是您使用 PropertyInfo 的地方。您正在运行时获取数据类型的结构。但这些在编译时是已知的。

【讨论】:

  • 我没有分析代码(响应 Dean Ward 的评论),但是当我调试时,它的反射速度非常快,但是当它进入 foreach 语句来设置 dataRow 值时从实体,它需要永远。它确实完成了,但在一分钟或更长时间之后。我不明白为什么只有大约 3000 行会这么慢。
  • 我听说你在编译时知道数据类型。我会不加思索地尝试一下,看看是否能解决问题。
  • 我可以肯定地说这不是反射的问题。创建和设置数据行时发生了一些奇怪的事情。
猜你喜欢
  • 2015-04-14
  • 2014-03-22
  • 2012-05-16
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多