使用实体框架中的AddRange进行大容量插入

本文关键字:大容量 插入 AddRange 实体 框架 | 更新日期: 2023-09-27 18:19:37

我使用实体框架中的AddRange在数据库中添加多个实体

foreach (string tagNumber in notPresent)
{
    element = new TagMaster { Name = Guid.NewGuid().ToString(), IsActive = true };
    element.TagCollections.Add(new TagCollection { TagNumber = tagNumber });
    newTagMasters.Add(element);
}
dbContext.TagMasters.AddRange(newTagMasters);
dbContext.SaveChanges();

我所期望的是,通过使用AddRange方法在上下文中添加完整的集合,将有一个查询发送到数据库。但令我惊讶的是,我看到每个要插入的记录都有多个插入语句。

有什么见解吗?

使用实体框架中的AddRange进行大容量插入

运行的问题是,遗憾的是,实体框架命令不知道批量插入。相反,它们会为要插入的每行生成一条语句。对此没有变通办法。

获得一个执行所有插入的语句的唯一可能性是使用特定的类或库。这里的例子是SqlBulkCopy,它不需要下载外部lib即可工作。

这里有一个指向msdn网站的链接:https://msdn.microsoft.com/de-de/library/system.data.sqlclient.sqlbulkcopy(v=vs.110).aspx

用法很简单。你只需要给构造函数你的连接(在事先打开它之后!),并告诉它应该向服务器写入什么以及目标表的名称是什么。然后你只需要在之后再次关闭连接。

sqlcon.Open();
using (SqlBulkCopy sqlBulkCopyVariable= new SqlBulkCopy(sqlcon))
{
    sqlBulkCopyVariable.BulkCopyTimeout = 600; // 10 minutes timeout
    sqlBulkCopyVariable.DestinationTableName = "targetTableName";
    sqlBulkCopyVariable.WriteToServer(MyData);
}
sqlcon.Close();

WriteToServer采用DataTable、DataReader甚至DataRow的数组。那里的确切实现将取决于你想如何向它提供数据。到目前为止,根据我的个人经验:这个类非常快,只生成一个语句。但它只适用于SqlClients。因此,如果你有一个不同的客户端,你需要查找哪个类或外部库最适合你。

恐怕通过Linq的插入并没有如您所期望的那样得到优化。正如您所观察到的,它通过多个插入语句来实现这一点。在这些情况下,您可以绕过Linq,转而使用批量复制替代方案(即:对于MS SQL server,使用SqlBulkCopy类,对于postgreSQL,使用Copy等)。