web-dev-qa-db-fra.com

Modification des types de données de colonne DataTable remplis

J'ai un System.Data.DataTable qui est rempli en lisant un fichier CSV qui définit le type de données de chaque colonne en chaîne.

Je souhaite ajouter le contenu de DataTable à une table de base de données existante. Cette opération est actuellement effectuée à l'aide de SqlBulkCopy avec DataTable comme source.

Toutefois, les types de données de colonne du DataTable doivent être modifiés pour correspondre au schéma de la table de base de données cible, gérant les valeurs NULL.

Je ne connais pas très bien ADO.NET, donc est-ce que je cherchais un moyen propre de le faire?

Merci.

11
TonE

Vous ne pouvez pas changer la DataType d'une DataColumn après l'avoir renseignée avec des données. Ce n'est pas une propriété en lecture seule, mais vous recevrez une exception au moment de l'exécution si vous essayez de la modifier après avoir déjà reçu des données.

De la documentation :

Une exception est générée lors de la modification de cette propriété une fois que la colonne a commencé à stocker des données.

Il vous faudra donc vous assurer que les types de colonne sont corrects au début (si possible) ou créer une nouvelle variable DataTable spécialement pour l'importation et copier les données de la variable DataTable d'origine.

Vous pouvez également écrire une classe IDataReader personnalisée qui lit votre DataTable et effectue une conversion juste à temps et la transmet à la SqlBulkCopy - ce serait beaucoup plus efficace, mais ce n'est évidemment pas une solution rapide.

10
Aaronaught

J'ai écrit cette fonction générique pour faire le travail, ça marche très bien pour moi:

public static bool ChangeColumnDataType(DataTable table, string columnname, Type newtype)
{
    if (table.Columns.Contains(columnname) == false)
        return false;

    DataColumn column= table.Columns[columnname];
    if (column.DataType == newtype)
        return true;

    try
    {
        DataColumn newcolumn = new DataColumn("temporary", newtype);
        table.Columns.Add(newcolumn);
        foreach (DataRow row in table.Rows)
        {
            try
            {
                row["temporary"] = Convert.ChangeType(row[columnname], newtype);
            }
            catch
            {
            }
        }
        table.Columns.Remove(columnname);
        newcolumn.ColumnName = columnname;
    }
    catch (Exception)
    {
        return false;
    }

    return true;
}

Vous pouvez simplement copier le code et le mettre dans une classe (MyClass ici), et l'utiliser comme ceci à titre d'exemple:

MyClass.ChangeColumnDataType(table, "GEOST", typeof (int));
9
Gisway

Assurez-vous de définir les types de données du datatable que vous remplissez.

Par exemple.:

    DataTable table = new DataTable("countries");
    table.Columns.Add("country_code", typeof (string));
    table.Columns.Add("country_name", typeof (string));
    //...
    //Fill table

Ou vous pouvez changer les types de colonne s'ils sont compatibles:

table.Columns["country_code"].DataType = typeof(string);
3
Carra

Si vous remplissez à partir d'un fichier csv, lisez d'abord le schéma dans datatable, changez le type de données de la colonne, puis remplissez le tableau. Exemple: J'utilise un fichier XML pour importer des données.

       DataSet dstemp = new DataSet();
       dstemp.ReadXmlSchema(@"D:\path of file\filename.xml");
       dstemp.Tables[0].Columns["Student_id"].DataType = typeof(Guid);
       dstemp.ReadXml(@"D:\path of file\filename.xml");

Je pense que cela devrait fonctionner pour vous.

1
Mayur

Tout comme "Eddie Monge Jr" ou "Gisway" ne peuvent pas l'obtenir.

mais avec le bon ordre de colonne.

public static bool ChangeColumnDataType(DataTable table, string columnname, Type newtype){
    if (table.Columns.Contains(columnname) == false)
        return false;

    DataColumn column = table.Columns[columnname];
    if (column.DataType == newtype)
        return true;

    try{
        DataColumn newcolumn = new DataColumn("temporary", newtype);
        table.Columns.Add(newcolumn);

        foreach (DataRow row in table.Rows){
            try{
                row["temporary"] = Convert.ChangeType(row[columnname], newtype);
            }
            catch{}
        }
        newcolumn.SetOrdinal(column.Ordinal);
        table.Columns.Remove(columnname);
        newcolumn.ColumnName = columnname;
    }
    catch (Exception){
        return false;
    }

    return true;
}
0
BenjaminR