我正在寻找插入实体框架的最快方法。

我之所以问这个问题,是因为您有一个活动的TransactionScope,并且插入量很大(4000+)。它可能会持续超过10分钟(事务的默认超时),这将导致事务不完整。


当前回答

这里编写的所有解决方案都无济于事,因为当您执行SaveChanges()时,insert语句会一个接一个地发送到数据库,这就是Entity的工作方式。

例如,如果您的数据库往返行程是50毫秒,那么插入所需的时间是记录数x 50毫秒。

您必须使用BulkInsert,以下是链接:https://efbulkinsert.codeplex.com/

通过使用它,我的插入时间从5-6分钟减少到10-12秒。

其他回答

我正在寻找插入实体框架的最快方法

有一些支持大容量插入的第三方库可用:

Z.EntityFramework.Extensions(推荐)EF实用程序实体框架.BulkInsert

请参见:实体框架大容量插入库

选择大容量插入库时要小心。只有实体框架扩展支持所有类型的关联和继承,并且它是唯一一个仍然受支持的实体框架扩展。


免责声明:我是实体框架扩展的所有者

此库允许您执行场景所需的所有批量操作:

批量保存更改大容量插入批量删除批量更新批量合并

实例

// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);

// Customize Primary Key
context.BulkMerge(customers, operation => {
   operation.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});

但是,对于超过(+4000)个插入,我建议使用存储过程。附上经过的时间。我确实插入了20英寸的11.788行

这就是代码

 public void InsertDataBase(MyEntity entity)
    {
        repository.Database.ExecuteSqlCommand("sp_mystored " +
                "@param1, @param2"
                 new SqlParameter("@param1", entity.property1),
                 new SqlParameter("@param2", entity.property2));
    }

您应该考虑为此使用System.Data.SqlClient.SqlBulkCopy。这是文档,当然还有很多在线教程。

抱歉,我知道您正在寻找一个简单的答案来让EF做您想做的事情,但批量操作并不是ORM真正的用途。

这种组合可以很好地提高速度。

context.Configuration.AutoDetectChangesEnabled = false;
context.Configuration.ValidateOnSaveEnabled = false;

使用此技术可以提高实体框架中插入记录的速度。这里我使用一个简单的存储过程来插入记录。为了执行这个存储过程,我使用实体框架的.FromSql()方法来执行Raw SQL。

存储过程代码:

CREATE PROCEDURE TestProc
@FirstParam VARCHAR(50),
@SecondParam VARCHAR(50)

AS
  Insert into SomeTable(Name, Address) values(@FirstParam, @SecondParam) 
GO

接下来,循环遍历所有4000条记录,并添加执行存储的

该过程每100次循环一次。

为此,我创建了一个字符串查询来执行这个过程,并继续将每一组记录附加到它。

然后检查循环是否以100的倍数运行,在这种情况下,使用.FromSql()执行它。

所以对于4000条记录,我只需要执行以下步骤4000/100=40次。

检查以下代码:

string execQuery = "";
var context = new MyContext();
for (int i = 0; i < 4000; i++)
{
    execQuery += "EXEC TestProc @FirstParam = 'First'" + i + "'', @SecondParam = 'Second'" + i + "''";

    if (i % 100 == 0)
    {
        context.Student.FromSql(execQuery);
        execQuery = "";
    }
}