简体   繁体   English

批量将多个文档插入SQL Server 2016

[英]Bulk Insert multiple documents into SQL server 2016

I am trying to bulk insert multiple documents(more than 50,000) from the folder. 我正在尝试从文件夹中批量插入多个文档(超过50,000个)。 I have this program works but it is time consuming. 我的程序可以运行,但是很费时间。 Please suggest any alternative ways. 请提出其他替代方法。

string[] files = Directory.GetFiles("C:\\TEST\\", "*.*", SearchOption.AllDirectories);
using (SqlConnection con= new SqlConnection (conString))
{
    con.Open();
     foreach (string docPath in files)
            {
                   byte[] file;    
                    using (var stream = new FileStream(docPath, FileMode.Open, FileAccess.Read))
                    {
                        using (var reader1 = new BinaryReader(stream))
                        {
                            file = reader1.ReadBytes((int)stream.Length);
                        }
                    }

        string insertSQLString = "INSERT INTO dbo.Test(content, path) VALUES(@File, @path)";
        using (SqlCommand cmd = new SqlCommand (insertSQLString, con))
        {
            cmd.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file;                             
            cmd.Parameters.Add("@path", SqlDbType.Text).Value = docPath;
            cmd.ExecuteNonQuery();
        }
    }
}

You can use the SqlBulkCopy class from System.Data.SqlClient for that. 您可以为此使用System.Data.SqlClientSqlBulkCopy类。 It is very efficient when inserting large bodies of data. 插入大量数据时,这非常有效。

Here you can find an example how that can be done: http://codinghelmet.com/?path=howto/bulk-insert 在这里,您可以找到一个如何完成此操作的示例: http : //codinghelmet.com/?path=howto/bulk-insert

Here are a couple of optimizations. 这里有一些优化。 There's no need to copy the file contents to a byte array before sending to SQL. 发送到SQL之前,无需将文件内容复制到字节数组。 You can pass a Stream directly. 您可以直接传递流。 See SqlClient Streaming Support . 请参见SqlClient流支持 And if the files are small, you'll want to batch a few together in a commit. 而且,如果文件很小,您将需要在提交中将它们分批处理。 Also it's unnecessary to recreate the SqlCommand each time. 另外,也不必每次都重新创建SqlCommand。

        static void Run()
        { 
            string[] files = Directory.GetFiles("C:\\TEST\\", "*.*", SearchOption.AllDirectories);
            using (SqlConnection con = new SqlConnection("server=localhost;database=testdb;integrated security=true"))
            {
                con.Open();
                string insertSQLString = "INSERT INTO dbo.Test(content, path) VALUES(@File, @path)";
                SqlCommand cmd = new SqlCommand(insertSQLString, con);
                var pFile = cmd.Parameters.Add("@File", SqlDbType.VarBinary, -1);
                var pPath = cmd.Parameters.Add("@path", SqlDbType.Text);

                var tran = con.BeginTransaction();
                var fn = 0;
                foreach (string docPath in files)
                {
                    fn += 1;
                    using (var stream = new FileStream(docPath, FileMode.Open, FileAccess.Read))
                    {
                        pFile.Value = stream;
                        pPath.Value = docPath;
                        cmd.Transaction = tran;
                        cmd.ExecuteNonQuery();
                        if (fn%10==0)
                        {
                            tran.Commit();
                            tran = con.BeginTransaction();
                            Console.Write("|");
                        }
                        Console.Write(".");
                    }
                }
                tran.Commit();
            }
        }

Another approach is to create a File Table and then just robocopy the files. 另一种方法是创建文件表 ,然后自动复制文件。

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

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