简体   繁体   English

使用 linq-to-sql 批量插入

[英]bulk insert with linq-to-sql

I have a query that looks like this:我有一个看起来像这样的查询:

using (MyDC TheDC = new MyDC())
{
   foreach (MyObject TheObject in TheListOfMyObjects)
   {
      DBTable TheTable = new DBTable();

      TheTable.Prop1 = TheObject.Prop1;
      .....
      TheDC.DBTables.InsertOnSubmit(TheTable);

   }
   TheDC.SubmitChanges();
}

This query basically inserts a list into the database using linq-to-sql.此查询基本上使用 linq-to-sql 将列表插入到数据库中。 Now I've read online that L2S does NOT support bulk operations.现在我在网上看到 L2S 不支持批量操作。 Does my query work by inserting each element at a time or all of them in one write?我的查询是通过一次插入每个元素还是在一次写入中插入所有元素?

Thanks for the clarification.感谢您的澄清。

I modified the code from the following link to be more efficient and used it in my application.我修改了以下链接中的代码以提高效率并在我的应用程序中使用它。 It is quite convenient because you can just put it in a partial class on top of your current autogenerated class.这非常方便,因为您可以将它放在当前自动生成的类之上的部分类中。 Instead of InsertOnSubmit add entities to a list, and instead of SubmitChanges call YourDataContext.BulkInsertAll(list) .而不是InsertOnSubmit将实体添加到列表,而不是SubmitChanges调用YourDataContext.BulkInsertAll(list)

http://www.codeproject.com/Tips/297582/Using-bulk-insert-with-your-linq-to-sql-datacontex http://www.codeproject.com/Tips/297582/Using-bulk-insert-with-your-linq-to-sql-datacontex

partial void OnCreated()
{
    CommandTimeout = 5 * 60;
}

public void BulkInsertAll<T>(IEnumerable<T> entities)
{                        
    using( var conn = new SqlConnection(Connection.ConnectionString))
    {
        conn.Open();

        Type t = typeof(T);

        var tableAttribute = (TableAttribute)t.GetCustomAttributes(
            typeof(TableAttribute), false).Single();
        var bulkCopy = new SqlBulkCopy(conn)
        {
            DestinationTableName = tableAttribute.Name
        };

        var properties = t.GetProperties().Where(EventTypeFilter).ToArray();
        var table = new DataTable();

        foreach (var property in properties)
        {
            Type propertyType = property.PropertyType;
            if (propertyType.IsGenericType &&
                propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                propertyType = Nullable.GetUnderlyingType(propertyType);
            }

            table.Columns.Add(new DataColumn(property.Name, propertyType));
        }

        foreach (var entity in entities)
        {
            table.Rows.Add(
                properties.Select(
                property => property.GetValue(entity, null) ?? DBNull.Value
                ).ToArray());
        }

        bulkCopy.WriteToServer(table);
    }                                               
}

private bool EventTypeFilter(System.Reflection.PropertyInfo p)
{
    var attribute = Attribute.GetCustomAttribute(p,
        typeof(AssociationAttribute)) as AssociationAttribute;

    if (attribute == null) return true;
    if (attribute.IsForeignKey == false) return true;

    return false;
}

The term Bulk Insert usually refers to the SQL Server specific ultra fast bcp based SqlBulkCopy implementation.术语Bulk Insert通常是指 SQL Server 特定的基于超快速 bcp 的SqlBulkCopy实现。 It is built on top of IRowsetFastLoad .它建立在IRowsetFastLoad 之上

Linq-2-SQL does not implement insert using this mechanism, under any conditions.任何情况下,Linq-2-SQL 都不会使用此机制实现插入。

If you need to bulk load data into SQL Server and need it to be fast, I would recommend hand coding using SqlBulkCopy.如果您需要将数据批量加载到 SQL Server 中并且需要它的速度,我建议使用 SqlBulkCopy 手动编码。

Linq-2-SQL will attempt to perform some optimisations to speed up multiple inserts, however it still will fall short of many micro ORMs (even though no micro ORMs I know of implement SqlBulkCopy) Linq-2-SQL 将尝试执行一些优化以加速多个插入,但是它仍然无法满足许多微 ORM(即使我知道没有实现 SqlBulkCopy 的微 ORM)

It will generate a single insert statement for every record, but will send them all to the server in a single batch and run in a single transaction.它将为每条记录生成一个插入语句,但会将它们全部发送到单个批处理中并在单个事务中运行。

That is what the SubmitChanges() outside the loop does.这就是循环外的 SubmitChanges() 所做的。

If you moved it inside, then every iteration through the loop would go off to the server for the INSERT and run in it's own transaction.如果你把它移到里面,那么循环中的每次迭代都会转到服务器进行 INSERT 并在它自己的事务中运行。

I don't believe there is any way to fire off a SQL BULK INSERT.我不相信有任何方法可以触发 SQL BULK INSERT。

LINQ Single Insert from List: LINQ 单从列表插入:

                int i = 0;
                foreach (IPAPM_SRVC_NTTN_NODE_MAP item in ipapmList)
                {
                    ++i;
                    if (i % 50 == 0)
                    {
                        ipdb.Dispose();
                        ipdb = null;
                        ipdb = new IPDB();
                        // .NET CORE
                        //ipdb.ChangeTracker.AutoDetectChangesEnabled = false; 
                        ipdb.Configuration.AutoDetectChangesEnabled = false;
                    }

                    ipdb.IPAPM_SRVC_NTTN_NODE_MAP.Add(item);
                    ipdb.SaveChanges();
                }                 

I would suggest you take a look at N.EntityFramework.Extension.我建议你看看 N.EntityFramework.Extension。 It is a basic bulk extension framework for EF 6 that is available on Nuget and the source code is available on Github under MIT license.它是 EF 6 的基本批量扩展框架,可在 Nuget 上获得,源代码可在 MIT 许可下在 Github 上获得。

Install-Package N.EntityFramework.Extensions

https://www.nuget.org/packages/N.EntityFramework.Extensions https://www.nuget.org/packages/N.EntityFramework.Extensions

Once you install it you can simply use BulkInsert() method directly on the DbContext instance.安装后,您可以直接在 DbContext 实例上直接使用 BulkInsert() 方法。 It support BulkDelete, BulkInsert, BulkMerge and more.它支持 BulkDelete、BulkInsert、BulkMerge 等。

BulkInsert()批量插入()

var dbcontext = new MyDbContext();  
var orders = new List<Order>();  
for(int i=0; i<10000; i++)  
{  
   orders.Add(new Order { OrderDate = DateTime.UtcNow, TotalPrice = 2.99 });  
}  
dbcontext.BulkInsert(orders);  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM