在Entity框架中使用AddRange批量插入

时间:2015-10-27 12:31:45

标签: c# entity-framework

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

任何见解?

2 个答案:

答案 0 :(得分:3)

您正在运行的问题是,遗憾的是实体框架命令知道没有批量插入。相反,它们每行生成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。因此,如果您有不同的客户端,则需要查找哪个类或外部库最适合您。

答案 1 :(得分:0)

我担心Linq的插入没有按照您的预期进行优化。它通过您观察到的多个插入语句来实现。您可以在这些情况下绕过Linq并使用批量复制替代方案(即:对于MS SQL服务器使用SqlBulkCopy类,对于postgreSQL使用复制等)。