2009-06-21 42 views
15

Tôi đang cố gắng chèn hàng loạt dữ liệu vào SQL 2008 bằng cách sử dụng SqlBulkCopy.Lỗi khi chèn dữ liệu bằng SqlBulkCopy

Đây là bàn của tôi:

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 

Dưới đây là mã của tôi:

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() 
    } 
} 

Vì vậy, tôi nhận được lỗi:

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

Tại sao ?? Lam sao tôi co thể sửa no? Làm ơn giúp tôi với!

Trả lời

19

Sử dụng tập lệnh bảng gốc của bạn, mã sau hoạt động.

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()); 
    } 
} 

Như đã nêu bởi Amal, bạn cần ánh xạ cột vì cột Identity.

+5

Không nên là "SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls"? – rusty

6

Loại ngày SQL khác với loại Ngày giờ SQL. Tôi nghĩ cột ngày trong bảng của bạn cần phải là kiểu DateTime, dựa trên cách bạn đang sử dụng nó.

SQL Date Type
SQL DateTime type

Cập nhật:

Tôi nghĩ rằng câu trả lời của Marc nên làm việc, nhưng có lẽ bạn cần phải xác định SqlBulkCopyColumnMappings từ DataTable nguồn của bạn đến đích, nếu không nó có thể nhận được các sai bản đồ vì cấu trúc của bảng đầu vào của bạn không khớp với bảng kết quả chính xác, tức là thứ tự của các cột ngày và hàng được hoán đổi.

ví dụ

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

Vâng, tôi hiểu rằng chúng khác nhau. Nhưng làm thế nào tôi có thể sử dụng chính xác DbType.Date nếu chỉ DbType.DateTime/SqlDateTime/DateTime là ở khắp mọi nơi ?! – abatishchev

+0

Bạn có thể sử dụng "DATETIME" được sử dụng rộng rãi hơn trong bảng tạm thời mà bạn sử dụng để tải hàng loạt và sau đó sử dụng "DATE" thực tế trong bảng dữ liệu "thực". Bạn có thể dễ dàng gán một DateTime cho một ngày trong một câu lệnh T-SQL. –

2

SqlDateTime đại diện cho ban datetime loại. Bạn đã thử chỉ sử dụng loại DateTime .NET trong số DataTable? Tôi hy vọng rằng nó có thể chuyển đổi nó thành một trong hai loại TSQL datetime hoặc date. Ditto decimal thay vì SqlDecimal.

+0

Nếu tôi sử dụng typeof (Double) hơn sẽ nhận được lỗi: "Giá trị cho trước của loại SqlString từ nguồn dữ liệu không thể được chuyển đổi sang kiểu thập phân của cột mục tiêu được chỉ định". Các lỗi tương tự với typeof (DateTime)! Và tôi không thể sử dụng typeof (thập phân) vì cột thích hợp đại diện cho tiền và yêu cầu 2 chữ số thập phân. – abatishchev

Các vấn đề liên quan