2009-06-21 3 views
15

Je suis en train de données d'insertion par lots dans SQL Server 2008 à l'aide SqlBulkCopy.erreur insertion de données à l'aide SqlBulkCopy

Voici ma table:

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 

Voici mon code:

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

Je suis en train d'erreur:

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

Pourquoi ?? Comment puis-je résoudre ce problème? Aidez-moi, s'il vous plaît!

Répondre

19

Utilisation de votre script de table d'origine, le code suivant fonctionne.

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

Comme déjà indiqué par Amal, vous avez besoin des mappages de colonnes à cause de la colonne Identité.

+5

Si pas être « SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls »? – rusty

6

Le type de date SQL est différent du type DateTime SQL. Je pense que la colonne de date dans votre table doit être de type DateTime, en fonction de la façon dont vous l'utilisez.

SQL Date Type
SQL DateTime type

Mise à jour:

Je pense que la réponse de Marc devrait fonctionner, mais vous avez probablement besoin de préciser les SqlBulkCopyColumnMappings de votre DataTable source à la destination, sinon il pourrait obtenir le mauvais mapping car la structure de votre table d'entrée ne correspond pas exactement à la table de sortie, c'est-à-dire que l'ordre des colonnes de date et de ligne est inversé.

par exemple

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

Oui, je comprends qu'ils sont différents. Mais comment puis-je utiliser exactement DbType.Date si seulement DbType.DateTime/SqlDateTime/DateTime est partout ?! – abatishchev

+0

Vous pouvez utiliser "DATETIME" plus largement utilisé dans la table temporaire que vous utilisez pour le chargement en bloc, puis utiliser "DATE" réel dans le tableau de données "réel". Vous pouvez facilement affecter un DateTime à une date dans une instruction T-SQL. –

2

SqlDateTime représente le type datetime d'origine. Avez-vous essayé d'utiliser le type DateTime .NET dans le DataTable? J'espère qu'il peut convertir cela en types TSQL datetime ou date. Idem decimal au lieu de SqlDecimal.

+0

Si j'utilise typeof (Double) que l'erreur se produira: "La valeur donnée de type SqlString de la source de données ne peut pas être convertie en type décimal de la colonne cible spécifiée". Les mêmes erreurs avec typeof (DateTime)! Et je ne peux pas utiliser typeof (décimal) parce que la colonne appropriée représente l'argent et nécessite 2 chiffres décimaux .. – abatishchev

Questions connexes