使用SqlBulkCopy插入数据时出错

问题描述:

我正尝试使用SqlBulkCopy将数据批量插入到SQL 2008中。使用SqlBulkCopy插入数据时出错

这里是我的表:

IF OBJECT_ID(N'statement', N'U') IS NOT NULL 
DROP TABLE [statement] 
GO 
CREATE TABLE [statement](
    [ID] INT IDENTITY(1, 1) NOT NULL, 
    [date] DATE NOT NULL DEFAULT GETDATE(), 
    [amount] DECIMAL(14,2) NOT NULL, 
CONSTRAINT [PK_statement] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

这里是我的代码:

private DataTable GetTable() 
{ 
    var list = new List<DataColumn>(); 
    list.Add(new DataColumn("amount", typeof(SqlDecimal))); 
    list.Add(new DataColumn("date", typeof(SqlDateTime))); 

    var table = new DataTable("statement"); 
    table.Columns.AddRange(list.ToArray()); 

    var row = table.NewRow(); 
    row["amount"] = (SqlDecimal)myObj.Amount; // decimal Amount { get; set; } 
    row["date"] = (SqlDateTime)myObj.Date; // DateTime Date { get; set } 
    table.Rows.Add(row); 

    return table; 
} 

private void WriteData() 
{ 
    using (var bulk = new SqlBulkCopy(strConnection, SqlBulkCopyOptions.KeepIdentity & SqlBulkCopyOptions.KeepNulls)) 
    { 
     //table.Columns.ForEach(c => bulk.ColumnMappings.Add(new SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName))); 
     bulk.BatchSize = 25; 
     bulk.DestinationTableName = "statement"; 
     bulk.WriteToServer(GetTable()); // a table from GetTable() 
    } 
} 

所以我得到的错误:

The given value of type SqlDateTime from the data source cannot be converted to type date of the specified target column.

为什么?我该如何解决这个问题?请帮帮我!

使用您的原始表脚本,以下代码工作。

private static DataTable GetTable() 
{ 
    var list = new List<DataColumn>(); 
    list.Add(new DataColumn("amount", typeof(Double))); 
    list.Add(new DataColumn("date", typeof(DateTime))); 
    var table = new DataTable("statement"); 
    table.Columns.AddRange(list.ToArray()); 

    var row = table.NewRow(); 
    row["amount"] = 1.2d; 
    row["date"] = DateTime.Now.Date; 

    table.Rows.Add(row); 
    return table; 
} 
private static void WriteData() 
{ 
    string strConnection = "Server=(local);Database=ScratchDb;Trusted_Connection=True;"; 
    using (var bulk = new SqlBulkCopy(strConnection, SqlBulkCopyOptions.KeepIdentity & SqlBulkCopyOptions.KeepNulls)) 
    { 
     bulk.ColumnMappings.Add(new SqlBulkCopyColumnMapping("amount", "amount")); 
     bulk.ColumnMappings.Add(new SqlBulkCopyColumnMapping("date", "date")); 
     bulk.BatchSize = 25; 
     bulk.DestinationTableName = "statement"; 
     bulk.WriteToServer(GetTable()); 
    } 
} 

正如Amal所述,由于标识列,您需要列映射。

SQL Date类型与SQL DateTime类型不同。我认为您表格中的日期列需要是DateTime类型,取决于您使用它的方式。

SQL Date Type
SQL DateTime type

更新:

我认为马克的回答应该工作,但你可能需要从源数据表到目的地指定SqlBulkCopyColumnMappings,否则可能会得到映射错误因为输入表的结构与输出表完全不匹配,即交换日期和行列的顺序。

例如

var amount = new SqlBulkCopyColumnMapping("amount", "amount"); 
var date = new SqlBulkCopyColumnMapping("date", "date"); 
bulk.ColumnMappings.Add(amount); 
bulk.ColumnMappings.Add(date); 
+0

是的,我明白他们是不同的。但是,如果只有DbType.DateTime/SqlDateTime/DateTime无处不在,我该如何使用完全DbType.Date?! – abatishchev 2009-06-21 14:49:12

+0

您可以在用于批量加载的临时表中使用更广泛使用的“DATETIME”,然后在“真实”数据表中使用实际的“DATE”。您可以在T-SQL语句中轻松地将日期时间分配给日期。 – 2009-06-21 18:49:08

SqlDateTime

表示原始datetime类型。您是否尝试过在DataTable中使用DateTime .NET类型?我希望它可以将其转换为TSQL datetimedate类型。同上decimal而不是SqlDecimal

+0

如果我使用typeof(Double)比将得到错误:“从数据源的SqlString类型的给定值不能转换为指定的目标列的十进制类型”。与typeof(DateTime)相同的错误!我不能使用typeof(十进制),因为适当的列代表金钱,并且需要2个十进制数字。 – abatishchev 2009-06-21 14:45:09