2015-10-27 326 views
1

我在数据库中的实体框架使用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方法添加上下文中的完整集合,将有是一个将被发送到数据库的单个查询。但令我惊讶的是,我看到要插入每个记录的多个插入语句。

任何见解?

+0

你期望看到什么SQL语句? – Heinzi

+1

我期待所有的插入语句将在一个批次中发送,而不是一个一个地发送。 –

+1

'AddRange'只是循环和执行多个'Add'语句的快捷方式。 – DavidG

回答

0

我很害怕通过Linq进行插入并不像您期望的那样优化。它是通过多次插入语句来完成的您可以在这些情况下绕过Linq,并使用批量复制替代方法(即:对于MS SQL服务器使用SqlBulkCopy类,对于PostgreSQL使用Copy等)。

3

您正在运行的问题是可悲的是实体框架命令知道没有批量插入。相反,它们会为您要插入的每行生成1条语句。 对此没有解决方法。

获得1个单一语句的唯一可能性就是使用特定的类或库。这里以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。因此,如果你有一个不同的客户端,你需要查找哪个类或外部库最适合你。