2009-01-13 15 views
19

Tengo un DataSet poblado de la hoja de Excel. Quería usar SQLBulk Copy para Insertar registros en la tabla Lead_Hdr donde LeadId es PK.SqlBulkCopy Not Working

estoy teniendo error al ejecutar el código de abajo:

El da ColumnMapping no coincide con ninguna columna en el origen o destino

string ConStr=ConfigurationManager.ConnectionStrings["ConStr"].ToString(); 

using (SqlBulkCopy s = new SqlBulkCopy(ConStr,SqlBulkCopyOptions.KeepIdentity)) 
{ 
    if (MySql.State==ConnectionState.Closed) 
    { 
     MySql.Open(); 
    } 

    s.DestinationTableName = "PCRM_Lead_Hdr"; 
    s.NotifyAfter = 10000; 

    #region Comment 
    s.ColumnMappings.Clear(); 

    #region ColumnMapping 
    s.ColumnMappings.Add("ClientID", "ClientID"); 
    s.ColumnMappings.Add("LeadID", "LeadID"); 
    s.ColumnMappings.Add("Company_Name", "Company_Name"); 
    s.ColumnMappings.Add("Website", "Website"); 
    s.ColumnMappings.Add("EmployeeCount", "EmployeeCount"); 
    s.ColumnMappings.Add("Revenue", "Revenue"); 
    s.ColumnMappings.Add("Address", "Address"); 
    s.ColumnMappings.Add("City", "City"); 

    s.ColumnMappings.Add("State", "State"); 
    s.ColumnMappings.Add("ZipCode", "ZipCode"); 
    s.ColumnMappings.Add("CountryId", "CountryId"); 

    s.ColumnMappings.Add("Phone", "Phone"); 
    s.ColumnMappings.Add("Fax", "Fax"); 
    s.ColumnMappings.Add("TimeZone", "TimeZone"); 
    s.ColumnMappings.Add("SicNo", "SicNo"); 
    s.ColumnMappings.Add("SicDesc", "SicDesc"); 

    s.ColumnMappings.Add("SourceID", "SourceID"); 
    s.ColumnMappings.Add("ResearchAnalysis", "ResearchAnalysis"); 
    s.ColumnMappings.Add("BasketID", "BasketID"); 
    s.ColumnMappings.Add("PipeLineStatusId", "PipeLineStatusId"); 

    s.ColumnMappings.Add("SurveyId", "SurveyId"); 
    s.ColumnMappings.Add("NextCallDate", "NextCallDate"); 
    s.ColumnMappings.Add("CurrentRecStatus", "CurrentRecStatus"); 
    s.ColumnMappings.Add("AssignedUserId", "AssignedUserId"); 
    s.ColumnMappings.Add("AssignedDate", "AssignedDate"); 
    s.ColumnMappings.Add("ToValueAmt", "ToValueAmt"); 
    s.ColumnMappings.Add("Remove", "Remove"); 
    s.ColumnMappings.Add("Release", "Release"); 

    s.ColumnMappings.Add("Insert_Date", "Insert_Date"); 
    s.ColumnMappings.Add("Insert_By", "Insert_By"); 
    s.ColumnMappings.Add("Updated_Date", "Updated_Date"); 
    s.ColumnMappings.Add("Updated_By", "Updated_By"); 

    #endregion 
    #endregion 

    s.WriteToServer(sourceTable); 

    s.Close(); 

    MySql.Close(); 
} 

Respuesta

22

Bueno, es que ¿derecho? ¿Los nombres de las columnas existen en ambos lados?

Para ser sincero, nunca me he molestado con las asignaciones. Me gusta mantener las cosas simples: tiendo a tener una tabla de etapas que se parece a la entrada en el servidor, luego I SqlBulkCopy en la tabla de etapas, y finalmente ejecuto un procedimiento almacenado para mover la tabla desde la tabla de etapas a la tabla actual; ventajas:

  • no hay problemas con la corrupción de datos en vivo si la importación falla en cualquier punto
  • puedo poner una transacción a la vuelta de la sproc
  • puedo tener el trabajo BCP sin registro, con la certeza de que la sproc se registrará
  • es ;-P sencilla (sin ensuciar con asignaciones)

Como reflexión final - si se trata de datos por lotes, se puede obtener un mejor rendimiento utilizando IDataReader (s dado que se trata de una API de transmisión, donde, como DataTable, es una API almacenada en búfer). Por ejemplo, tiendo a enganchar las importaciones de CSV usando CsvReader como fuente de una SqlBulkCopy. Alternativamente, he escrito cuñas alrededor de XmlReader para presentar cada elemento de primer nivel como una fila en un IDataReader - muy rápido.

+2

Bueno, yo soy nuevo en esto "puesta en escena" plazo puede usted explicar un –

+6

Una tabla provisional de bits es una tabla que se volcar sus datos en. A menudo, no tiene un índice, por lo que la escritura es más rápida. Vierta en una tabla de etapas, manipule los datos y escriba de la transición a sus tablas de producción usando un procedimiento almacenado (envuélvalos en una transacción para protegerlos de la corrupción). –

+3

Recuerde que los datos de la tabla de etapas son transitorios, por lo que debe eliminarlos antes de ingresar los datos, y no usarlos para recuperar los datos, excepto para transformarlos y enviarlos a otro conjunto de tablas. Además, recuerde que los datos por etapas tienden a ser menos normales que sus datos "reales". –

2

La respuesta de Marc sería mi recomendación (sobre el uso de la tabla de etapas). Esto garantiza que si su fuente no cambia, tendrá menos problemas de importación en el futuro.

Sin embargo, en mi experiencia, puede comprobar las siguientes cuestiones:

Columna partido nombres de la fuente y la tabla Que los tipos de columna coinciden

Si usted piensa que usted hizo esto y todavía sin éxito. Puedes probar lo siguiente.

1 - Permitir nulos en todas las columnas de la tabla 2 - comentarios todas las asignaciones de columnas 3 - vuelva a ejecutar la adición de una columna a la vez hasta que encuentre en su problema es

Eso debe llevar a cabo el error

0

Lo que he encontrado es que las columnas en la tabla y las columnas en la entrada deben al menos coincidir. Puede tener más columnas en la tabla y la entrada aún se cargará. Si tienes menos, recibirás el error.

37

He encontrado el mismo problema al copiar datos de acceso a SQLSERVER 2005 y encontré que las asignaciones de columna son sensibles a las mayúsculas y minúsculas en ambas fuentes de datos, independientemente de la sensibilidad de las bases de datos.

+0

Tuve el mismo problema, hay un error activo: http://connect.microsoft.com/VisualStudio/feedback/details/94135/sqlbulkcopy-column-mappings- mayúsculas/minúsculas – marcob

+2

Estoy usando SQL SERVER 2008 R2. Y esto sigue siendo un problema también. Así que, cuidadosas personas, la columna sigue siendo sensible a mayúsculas y minúsculas en Sql 2008 aparentemente (en el año 2013). También actualicé mi sql server 2008 R2 al último service pack, etc. –

+0

OMG me estaba volviendo loco con este estúpido problema, ¡¡¡gracias !!! ~ !!!!! – Liran

0

Pensó largo tiempo en responder ... Incluso si los nombres de las columnas son iguales, si el tipo de datos difiere se obtiene el mismo error. Por lo tanto, verifique los nombres de las columnas y su tipo de datos.

P.S .: las tablas de etapas son definitivamente la forma de importar.

1

Una de las razones es que: SqlBukCOpy distingue entre mayúsculas y minúsculas. Siga los pasos:

  1. En ese caso primero hay que encontrar su columna del cuadro Fuente por el uso de "contener" método en C#.
  2. Una vez que su columna de destino coincide con la columna de origen, obtenga el índice de y proporcione su nombre de columna en SqlBukCOpy.

Por ejemplo: `

//Get Column from Source table 
    string sourceTableQuery = "Select top 1 * from sourceTable"; 
    DataTable dtSource=SQLHelper.SqlHelper.ExecuteDataset(transaction, CommandType.Text, sourceTableQuery).Tables[0];// i use sql helper for executing query you can use corde sw 

for (int i = 0; i < destinationTable.Columns.Count; i++) 
         { //check if destination Column Exists in Source table 
          if (dtSource.Columns.Contains(destinationTable.Columns[i].ToString()))//contain method is not case sensitive 
          { 
           int sourceColumnIndex = dtSource.Columns.IndexOf(destinationTable.Columns[i].ToString());//Once column matched get its index 
           bulkCopy.ColumnMappings.Add(dtSource.Columns[sourceColumnIndex].ToString(), dtSource.Columns[sourceColumnIndex].ToString());//give coluns name of source table rather then destination table so that it would avoid case sensitivity 
          } 

         } 
         bulkCopy.WriteToServer(destinationTable); 
         bulkCopy.Close(); 
0

Me gustaría ir con la idea puesta en escena, sin embargo, aquí es mi método para manejar la naturaleza sensible caso. Feliz de ser objeto de crítica en mi LINQ

using (SqlConnection connection = new SqlConnection(conn_str)) 
{ 
     connection.Open(); 
     using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) 
     { 
      bulkCopy.DestinationTableName = string.Format("[{0}].[{1}].[{2}]", targetDatabase, targetSchema, targetTable); 
      var targetColumsAvailable = GetSchema(conn_str, targetTable).ToArray(); 
      foreach (var column in dt.Columns) 
      { 
       if (targetColumsAvailable.Select(x => x.ToUpper()).Contains(column.ToString().ToUpper())) 
       { 
        var tc = targetColumsAvailable.Single(x => String.Equals(x, column.ToString(), StringComparison.CurrentCultureIgnoreCase)); 
        bulkCopy.ColumnMappings.Add(column.ToString(), tc); 
       } 
      } 

      // Write from the source to the destination. 
      bulkCopy.WriteToServer(dt); 
      bulkCopy.Close(); 
     } 
} 

y el método de ayuda

private static IEnumerable<string> GetSchema(string connectionString, string tableName) 
     { 



    using (SqlConnection connection = new SqlConnection(connectionString)) 
     using (SqlCommand command = connection.CreateCommand()) 
     { 
      command.CommandText = "sp_Columns"; 
      command.CommandType = CommandType.StoredProcedure; 

      command.Parameters.Add("@table_name", SqlDbType.NVarChar, 384).Value = tableName; 

      connection.Open(); 
      using (var reader = command.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        yield return (string)reader["column_name"]; 
       } 
      } 
     } 
    }