2009-06-21 16 views
15

Sto tentando di inserire in batch i dati in SQL 2008 utilizzando SqlBulkCopy.Errore durante l'inserimento dei dati utilizzando SqlBulkCopy

Ecco il mio tavolo:

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 

Qui è il mio codice:

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

Così sto ottenendo errore:

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

Perché ?? Come posso ripararlo? Aiutami per favore!

risposta

19

Utilizzando lo script di tabella originale, il seguente codice funziona.

Come già affermato da Amal, è necessario il mapping delle colonne a causa della colonna Identità.

+5

Non dovrebbe essere "SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls"? – rusty

6

Il tipo di data SQL è diverso dal tipo DateTime SQL. Penso che la colonna della data nella tabella deve essere di tipo DateTime, in base al modo in cui lo si utilizza.

SQL Date Type
SQL DateTime type

Aggiornamento:

Credo che la risposta di Marc dovrebbe funzionare, ma probabilmente necessario specificare lo SqlBulkCopyColumnMappings dal DataTable sorgente alla destinazione, altrimenti potrebbe essere sempre dalla parte del torto mappatura perché la struttura della tabella di input non corrisponde esattamente alla tabella di output, ad esempio l'ordine di data e le colonne di riga scambiate.

es

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

Sì, capisco che sono diversi. Ma come posso usare esattamente DbType.Date se solo DbType.DateTime/SqlDateTime/DateTime è ovunque ?! – abatishchev

+0

È possibile utilizzare il "DATETIME" più utilizzato nella tabella temporanea che si utilizza per il caricamento in blocco, quindi utilizzare la "DATA" effettiva nella tabella dei dati "reale". È possibile assegnare facilmente un DateTime a una data in un'istruzione T-SQL. –

2

SqlDateTime rappresenta il datetime tipo originale. Hai provato a utilizzare il tipo DateTime .NET nello DataTable? Spero che possa convertirlo in entrambi i tipi TSQL datetime o date. Idem decimal anziché SqlDecimal.

+0

Se si utilizza typeof (Double) di otterrà errore: "Il valore dato di tipo SqlString dall'origine dati non può essere convertito in tipo decimale della colonna di destinazione specificata". Gli stessi errori con typeof (DateTime)! E non posso usare typeof (Decimal) perché la colonna appropriata rappresenta denaro e richiede 2 cifre decimali. – abatishchev

Problemi correlati