Изменение заполненных типов данных столбца DataTable

Абстрактные методы - это те, которые вы должны определить, когда вы наследуете эту ABC.

В столбце Mixin перечислены методы, которые вы можете использовать впоследствии, вы получаете их бесплатно, наследуя не от object, но от этой ABC. Если вы определяете __getitem__, вы можете автоматически использовать __iter__ впоследствии, например.

Еще одно преимущество наследования от этих классов - это то, что каждый может видеть после этого, каким должен был быть ваш класс, поскольку он issubclass(your_class, any_ABC), а любой экземпляр - isinstance(your_object, any_ABC). Но это написано в учебнике после таблицы, которую вы опубликовали.

12
задан TonE 29 March 2010 в 14:16
поделиться

3 ответа

Вы не можете изменить DataType DataColumn после заполнения его данными. Это свойство не только для чтения, но вы получите исключение во время выполнения, если попытаетесь изменить его после того, как у него уже есть данные.

Из документации :

Исключение создается при изменении этого свойства после того, как столбец начал хранить данные.

Таким образом, вам нужно будет либо обеспечить правильные типы столбцов в начале (если возможно), либо создать новую DataTable специально для импорта и копирования данных из исходной DataTable .

Вы также можете написать собственный класс IDataReader , который читает из вашего DataTable , выполняет своевременное преобразование и передает его в SqlBulkCopy - it было бы намного эффективнее, но это, очевидно, не быстрое решение.

10
ответ дан 2 December 2019 в 06:08
поделиться

Я создал улучшенную версию Gisway / Yuri Galanter решение, которое обращается к следующим моментам:

  • не едят исключения , перестали работать рано
  • , Сохраняют nullability / AllowDBNull из первоначального столбца
  • , Работа со столбцом возражает непосредственно, никакая потребность в объекте таблицы как параметр
  • , именование Изменения к типичным конвенциям .NET
  • Улучшается, документы
  • Включают гуид во временное имя столбца, чтобы действительно избежать, чтобы коллизии
  • Осуществили рефакторинг, чтобы быть дополнительными методами

Как проект, в котором я нуждался, это для находится в VB.Net, мое решение записано (и протестировано) в нем также, извините - преобразование не должно быть трудным все же.

' following methods will be defined in a module, which is why they aren't Shared
' based on https://codecorner.galanter.net/2013/08/02/ado-net-datatable-change-column-datatype-after-table-is-populated-with-data/ 
' and https://stackoverflow.com/a/15692087/1200847 

''' <summary> 
''' Converts DataType of a DataTable's column to a new type by creating a copy of the column with the new type and removing the old one. 
''' </summary> 
''' <param name="table">DataTable containing the column</param> 
''' <param name="columnName">Name of the column</param> 
''' <param name="newType">New type of the column</param> 
<Extension()> 
Public Sub ChangeColumnDataType(table As DataTable, columnName As String, newType As Type) 
    If Not table.Columns.Contains(columnName) Then Throw New ArgumentException($"No column of the given table is named ""{columnName}"".") 
    Dim oldCol As DataColumn = table.Columns(columnName) 
    oldCol.ChangeDataType(newType) 
End Sub 

''' <summary> 
''' Converts DataType of a DataTable's column to a new type by creating a copy of the column with the new type and removing the old one. 
''' </summary> 
''' <param name="column">The column whichs type should be changed</param> 
''' <param name="newType">New type of the column</param> 
<Extension()> 
Public Sub ChangeDataType(column As DataColumn, newType As Type) 
    Dim table = column.Table 
    If column.DataType Is newType Then Return 

    Dim tempColName = "temporary-327b8efdb7984e4d82d514230b92a137" 
    Dim newCol As New DataColumn(tempColName, newType) 
    newCol.AllowDBNull = column.AllowDBNull 

    table.Columns.Add(newCol) 
    newCol.SetOrdinal(table.Columns.IndexOf(column)) 

    For Each row As DataRow In table.Rows 
        row(tempColName) = Convert.ChangeType(row(column), newType) 
    Next 
    table.Columns.Remove(column) 
    newCol.ColumnName = column.ColumnName 
End Sub

, Если Вы т.е. имеете int столбец, который действительно должен быть bool столбец, используйте его как это:

table.Columns("TrueOrFalse").ChangeDataType(GetType(Boolean)) 

Важный : Поскольку это изменяет DataTable, Вы возможный хотите сделать это правильно после загрузки данных и принять изменения впоследствии. Таким образом, отслеживание изменений, связывая с данными и т.д. работает обычно впоследствии:

table.AcceptChanges()
<час>

, Если non-nullability Вашего столбца не настроен правильно при загрузке данных, поскольку это имело место для моего столбца Oracle NUMBER(1,0) NOT NULL, можно хотеть ввести код как это:

table.Columns("TrueOrFalse").AllowDBNull = False 
table.Columns("TrueOrFalse").DefaultValue = 0
0
ответ дан 2 December 2019 в 06:08
поделиться

Обязательно установите типы данных для заполняемой вами таблицы данных.

Например:

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

Или вы можете изменить типы столбцов, если они совместимы:

table.Columns["country_code"].DataType = typeof(string);
3
ответ дан 2 December 2019 в 06:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: