2

我在不同的机器上使用 2 个 SQL 2008 服务器。服务器名称是source.ex.comdestination.ex.com

destination.ex.com已链接到source.ex.com并具有适当的权限source.ex.com以写入调用的bacon-wrench数据库 destination.ex.com

source.ex.com我已经通过短信登录并测试了这个查询(成功):

INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
(PunchID, BaconID) VALUES (4,6);

在 C# .NET 4.0 网页中,我连接到source.ex.com并执行类似的查询(成功):

using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
    c.Open();
    String sql = @"
        INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
        (PunchID, BaconID) VALUES (34,56);";
    using(SqlCommand cmd = new SqlCommand(sql, c))
    {
        cmd.ExecuteNonQuery();
    }
}

对于一小组插入语句(比如 20 个或更少),执行以下操作可以正常执行:

using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
    c.Open();
    String sql = @"
        INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
         (PunchID, BaconID) VALUES (34,56);
        INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
         (PunchID, BaconID) VALUES (22,11);
        INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
         (PunchID, BaconID) VALUES (33,55);
        INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
         (PunchID, BaconID) VALUES (1,2);";
    using(SqlCommand cmd = new SqlCommand(sql, c))
    {
        cmd.ExecuteNonQuery();
    }
}

我正在尝试用大约 20000 条记录来做这样的事情。上述方法需要 11 分钟才能完成——我认为这是服务器对我发出尖叫以使其成为某种批量操作。从其他 StackOverflow 线程SqlBulkCopy中推荐了该类,并将其作为参数DataTable,完美!

因此,我构建了一个 DataTable 并尝试将其写入服务器(失败):

DataTable dt = new DataTable();
dt.Columns.Add("PunchID", typeof(int));
dt.Columns.Add("BaconID", typeof(int));
for(int i = 0; i < 20000; i++)
{
    //I realize this would make 20000 duplicate 
    //rows but its not important 
    dt.Rows.Add(new object[] {
        11, 33 
    });
}

using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
    c.Open();
    using(SqlBulkCopy bulk = new SqlBulkCopy(c))
    {
        bulk.DestinationTableName = "[destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]";
        bulk.ColumnMappings.Add("PunchID", "PunchID");
        bulk.ColumnMappings.Add("BaconID", "BaconID");
        bulk.WriteToServer(dt);
    }
}

EDIT2:以下消息是我试图修复的:

网页崩溃bulk.WriteToServer(dt);并显示错误消息Database bacon-wrench does not exist please ensure it is typed correctly.我做错了什么?如何更改它以使其正常工作?

编辑1:

我能够使用以下语法显着加快查询速度。但是对于这么小的记录集,它仍然很慢。

using(SqlConnection c = new SqlConnection(ConfigurationManager.ConnectionStrings["SOURCE"].ConnectionString))
{
    c.Open();
    String sql = @"
        INSERT INTO [destination.ex.com].[bacon-wrench].[dbo].[tblFruitPunch]
         (PunchID, BaconID) VALUES 
         (34,56),
         (22,11),
         (33,55),
         (1,2);";
    using(SqlCommand cmd = new SqlCommand(sql, c))
    {
        cmd.ExecuteNonQuery();
    }
}
4

2 回答 2

1

如果您使用的是 SQL Server 2008+,则可以引入 Table 用户数据类型。准备类型、接收表和存储过程,如下所示。数据类型和存储过程在本地系统上。我一般在代码中有一个if语句检测表是远程还是本地,远程我这样做,本地我用SqlBulkCopy。

if(TYPE_ID(N'[Owner].[TempTableType]') is null)
begin
CREATE TYPE [Owner].[TempTableType] AS TABLE ( [PendingID] uniqueidentifier, [Reject] bit)
end
IF  NOT EXISTS (SELECT * FROM [LinkedServer].[DatabaseOnLS].sys.tables where name = 'TableToReceive') 
EXEC('
CREATE TABLE [DatabaseOnLS].[Owner].[TableToReceive] ( [PendingID] uniqueidentifier, [Reject] bit)
') AT [LinkedServer]
else
EXEC('
TRUNCATE TABLE [DatabaseOnLS].[Owner].[TableToReceive]
') AT [LinkedServer]

CREATE PROCEDURE [Owner].[TempInsertTable]
@newTableType TempTableType readonly
AS
BEGIN
insert into [LinkedServer].[DatabaseOnLS].[Owner].[TableToReceive] select * from @newTableType 
END

在 C# 代码中,您可以执行以下操作将 DataTable 插入到链接服务器上的表中(我正在使用现有的 UnitOfWork,它已经具有连接和事务):

using (var command = new SqlCommand("TempInsertTable",
                    oUoW.Database.Connection as SqlConnection) { CommandType = CommandType.StoredProcedure }
                )
{
    command.Transaction = oUoW.Database.CurrentTransaction as SqlTransaction;
    command.Parameters.Add(new SqlParameter("@newTableType", oTempTable));
    drResults = command.ExecuteReader();
    drResults.Close();
}
于 2016-06-06T21:22:58.837 回答
0

在尝试了包括链接服务器设置、排序规则、同义词等在内的许多事情之后,我最终得到了这个错误消息:

Inserting into remote tables or views is not allowed by using the BCP utility or by using BULK INSERT.

也许您可以批量插入到本地服务器上的临时表(您的代码可以正常工作),然后从该临时表插入到链接服务器,然后本地删除临时表。您必须测试性能。

于 2013-01-25T22:24:12.350 回答