向数据库里插数据有什么好的办法

射手座cl 2019-01-11 11:36:56
问题:从接口中取数据50年,由于数据量较大所以考虑的递归一年一年的取数据,在向数据库中插数据时用的下面的方法,每次大概递归到第3次,就会报异常System.OutOfMemoryException,数据库的大神们有没有什么好的办法向数据库中批量添加数据
#region 批量添加DataTable
/// <summary>
/// 批量添加datatable
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public bool Insert(DataTable data)
{
try
{
//连接sql数据库语句
using (SqlConnection conn = new SqlConnection("data source=.;initial catalog=YzSystem;persist security info=True;user id=sa;password=xxx;"))
{
if (conn.State != ConnectionState.Open)
conn.Open();
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(conn))
{

// 列映射集合。
sqlBulkCopy.ColumnMappings.Add(0, "ID");
sqlBulkCopy.ColumnMappings.Add(1, "EvaluatorID");
sqlBulkCopy.ColumnMappings.Add(2, "CriticID");
sqlBulkCopy.ColumnMappings.Add(3, "IsEvaluated");
sqlBulkCopy.ColumnMappings.Add(4, "Weight");
sqlBulkCopy.ColumnMappings.Add(5, "Year");
sqlBulkCopy.ColumnMappings.Add(6, "EvaluationInfoID");
sqlBulkCopy.ColumnMappings.Add(7, "IsUsed");

// 每一批次中的行数。在每一批次结束时,将该批次中的行发送到服务器。
sqlBulkCopy.BatchSize = data.Rows.Count;

// 超时之前操作完成所允许的秒数。
sqlBulkCopy.BulkCopyTimeout = 60;
// 服务器上目标表的名称。
sqlBulkCopy.DestinationTableName ="YzSettingEvaluationEntity";

// 将data这个datatable中的表复制到目标表中。
sqlBulkCopy.WriteToServer(data);
}
if (conn.State != ConnectionState.Closed)
conn.Close();
return true;
}
}
catch (Exception ex)
{
return false;
}
}
#endregion
...全文
147 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
射手座cl 2019-01-12
  • 打赏
  • 举报
回复
引用 6 楼 吉普赛的歌 的回复:
没办法两全的了, 又要马儿跑又要马儿不吃草没那么好的事。 跟上级沟通下。
好的
射手座cl 2019-01-12
  • 打赏
  • 举报
回复
引用 7 楼 砸死牛顿的苹果 的回复:
为什么不是 只 处理新增和差异部分
目标数据库是新建的,所以相当于数据都是新增的
  • 打赏
  • 举报
回复
为什么不是 只 处理新增和差异部分
吉普赛的歌 版主 2019-01-11
  • 打赏
  • 举报
回复
没办法两全的了, 又要马儿跑又要马儿不吃草没那么好的事。 跟上级沟通下。
吉普赛的歌 版主 2019-01-11
  • 打赏
  • 举报
回复
引用 4 楼 射手座cl 的回复:
[quote=引用 3 楼 吉普赛的歌 的回复:]
SELECT 3500*365*50
/*
63875000
*/
这么大的数据量, 哪里还能用什么接口? 直接导出为 csv 文件,拿到目标服务器导入就是了。 如果两台机能直接互联的话, 直接用 sqlserver 的导入导出向导。 如果源数据不是 sqlserver , 目标是 sqlserver 。或者两者都是 sqlserver 也可以这么操作: 手写程序, sqlbulkcopy 支持目标为 sqlserver 的写入, 而不管源是什么。 源设置为为 IDataReader (不要用 datatable ), 边读边写, 效率也很高的。
数据源是webservice接口,应该是省内共享的,为了数据统一,我也没办法[/quote] 这么大的数据量, 不可能天天传来传去吧? 如果是一次性导入的, 你按我说的, 在源上面用 csv 文件导出, 在目标机上导入。 如果真的是天天都要做, 那用接口是不现实的, 速度太慢, 限制太大。 天天要做, 那只能直接开放数据库连接, 用我上面所说的 sqlbulkcopy 的边读边写的办法(红字部分)。
射手座cl 2019-01-11
  • 打赏
  • 举报
回复
引用 3 楼 吉普赛的歌 的回复:
SELECT 3500*365*50
/*
63875000
*/


这么大的数据量, 哪里还能用什么接口?
直接导出为 csv 文件,拿到目标服务器导入就是了。

如果两台机能直接互联的话, 直接用 sqlserver 的导入导出向导。

如果源数据不是 sqlserver , 目标是 sqlserver 。或者两者都是 sqlserver 也可以这么操作:
手写程序, sqlbulkcopy 支持目标为 sqlserver 的写入, 而不管源是什么。
源设置为为 IDataReader (不要用 datatable ), 边读边写, 效率也很高的。

数据源是webservice接口,应该是省内共享的,为了数据统一,我也没办法
吉普赛的歌 版主 2019-01-11
  • 打赏
  • 举报
回复
SELECT 3500*365*50
/*
63875000
*/
这么大的数据量, 哪里还能用什么接口? 直接导出为 csv 文件,拿到目标服务器导入就是了。 如果两台机能直接互联的话, 直接用 sqlserver 的导入导出向导。 如果源数据不是 sqlserver , 目标是 sqlserver 。或者两者都是 sqlserver 也可以这么操作: 手写程序, sqlbulkcopy 支持目标为 sqlserver 的写入, 而不管源是什么。 源设置为为 IDataReader (不要用 datatable ), 边读边写, 效率也很高的。
射手座cl 2019-01-11
  • 打赏
  • 举报
回复
引用 1 楼 吉普赛的歌 的回复:
哪有你这么玩的。
一个 datatable 消耗内存就不得了。

这里要改:
sqlBulkCopy.BatchSize = data.Rows.Count;
=》
sqlBulkCopy.BatchSize = 1000;

一批全部插入, 算大事务, 数据量大了很容易出问题。

额。。。,后来发现一年数据太多了,就把递归改成for循环了,改成取一天数据,存一天数据了。
一天数据大概3500条,但是每次从接口取数据特别费时间,50年每年取365次大概18000次取存,又太慢了,这还只是一个表。有没有好的方法
吉普赛的歌 版主 2019-01-11
  • 打赏
  • 举报
回复
哪有你这么玩的。 一个 datatable 消耗内存就不得了。 这里要改: sqlBulkCopy.BatchSize = data.Rows.Count; =》 sqlBulkCopy.BatchSize = 1000; 一批全部插入, 算大事务, 数据量大了很容易出问题。

34,594

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧