【问题标题】:How to export large archive table as CSV with Entity Framework?如何使用实体框架将大型存档表导出为 CSV?
【发布时间】:2020-01-19 02:45:23
【问题描述】:

我们有一个 ASP.NET MVC Web 应用程序,它使用 EF6 与 MS SQL Server Epress 数据库通信。在数据库中,我们有一个大于 10 mio 的大型存档表。行。归档表比较简单,就是几个id、一个值和一个时间戳。

我已经有一个“工作”控制器方法,它从我的 DbContext 中获取数据作为我的 archiveEntry 实体的 IQueryable,然后将其放入带有 .ToList() 的列表中,从中创建一个 CSV 文件,压缩它然后将其作为文件下载返回给客户端。但是,问题是整个表太慢了,250000 行这需要大约 15 分钟。

有没有办法直接在数据库中查询和创建 CSV 并将其传递给客户端?

【问题讨论】:

  • 15 分钟是全部时间。什么时候只抓取数据?我认为在“SQL Server 格式”或“CSV 格式”上,必须将相同数量的数据从 SQL 传递到 ASP.Net
  • 这里必须使用实体吗?绕过对象接口(例如使用 SSIS 或 bcp)将真正节省您的时间。
  • 你可以写一个CLR scalar function
  • 我以前遇到过这个问题。使用用于存档数据库的 sqlcmd.exe 非常快,并且运行速度比 c# 中的查询快得多(请参阅:docs.microsoft.com/en-us/sql/tools/…)您可以将输出指定为 csv。我通常从 c# 创建一个 bat 文件,然后将 bat 作为进程运行。您也可以只使用 Process 并且 c# 查询语句是 sqlcmd 的参数。使用 sqlcmd.exe 在几分钟内运行了一个占用超过 1/2 小时的 C# 查询。

标签: c# sql-server asp.net-mvc entity-framework csv


【解决方案1】:

您可以用“Dapper”之类的更快的方式替换 EF 来读取您的实体。

更多信息在这里:https://dapper-tutorial.net/dapper

如果您想保留 EF,另一种方法是从您的上下文中禁用更改跟踪(因为您只是在读取您的实体)

你有两种选择:

  1. myContext.AutoDetectChangesEnabled = false;
  2. var logs= myContext.Logs.AsNoTracking();

然后使用高性能 CSV 写入器:

这个不错:https://joshclose.github.io/CsvHelper/

【讨论】:

  • 在我的情况下有点过头了,但是 +1 是为了了解 dapper,它看起来对其他一些项目很有趣!
【解决方案2】:

通过这些步骤,我设法将时间从几分钟缩短到 2 秒:

首先,我在我的上下文(名为“db”)配置中禁用了一些设置:

db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;

然后,我在我的数据库上运行原始 SQL 查询:

var result = db.Database.SqlQuery<ValueArchive>("select * from ValueArchive").ToList();

最后我注意到,通过使用 StringBuilder 而不是向 String 变量添加新行,构建 CSV 字符串得到了极大的改进。

【讨论】:

  • 不要重新发明轮子,有很多优秀的 csv 编写器。你必须处理很多问题(编码、特殊字符)
猜你喜欢
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
相关资源
最近更新 更多