Относительно вашего основного вопроса: «Есть ли способ для меня использовать этот метод, но установить для полей их надлежащие форматы, чтобы они могли go в правильно определенной таблице sql?» Да .
Вы могли бы привести значения к нужным им типам перед созданием DataTable (пример кода ниже). Лично я, вероятно, попытался бы заменить файлы CSV чем-то, что кодирует информацию о типе, например JSON или паркет.
ОБНОВЛЕНИЕ НА ОСНОВЕ ВОПРОСОВ ОП:
Должен ли я прописать каждое поле в этом l oop, или только те, которые нужно изменить со строки на что-то еще? Вам нужно сопоставить каждое поле с [PSCustomObject]
, но вы только Нужно привести поля, содержащие данные, которые должны быть не строковыми.
Для заголовков столбцов, в которых есть пробелы, заключать их в квадратные скобки при обращении к ним в PS (например, [Дата создания]) Я скорректировал ответ, чтобы проиллюстрировать один из возможных способов обрабатывать заголовки столбцов с пробелами. См. Столбец 'e e'.
Я вижу, что ваш пример преобразует числа типа 0,2 в "double". Мои десятичные данные будут в валюте и будут работать с другими данными, так что я установлю их в десятичном виде. Ожидаете ли вы, что это будет проходить правильно, или существует другой правильный синтаксис для преобразования в десятичное число? Исходя из приведенной ниже ссылки, десятичный тип. NET должен отображаться на SQL десятичный тип сервера. Смотрите свойство f в данных примера. https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-data-type-mappings
При условии, что у вас есть следующие данные в CSV
a,b,c,d,e e,f
string1,1,0.1,2020-05-02 14:29:06.780,e,1.99
string2,2,0.2,2020-05-03 01:01:02.000,e,3.59
Вы можете привести значение к желаемому типы, использующие подход, аналогичный описанному в foreach
l oop ниже. Очевидно, вам придется настроить его под свои фактические данные.
param(
$datasource = 'localhost',
$db = 'test',
$destTable = 'table',
$csvPath = "$PSScriptRoot\data.csv"
)
$ConnectionString = "Data Source=$datasource; Database=$db;Trusted_Connection=True;";
. "$PSScriptRoot\Out-DataTable.ps1"
$rawData = Import-CSV -Path $csvPath
$typedData = @()
foreach ($row in $rawData) {
$tempObj = [PSCustomObject] @{
a = $row.a
b = [int] $row.b
c = [double] $row.c
d = [datetime] $row.d
e_e = $row."e e"
f = [decimal] $row.f
}
$typedData += $tempObj
}
$csvDataTable = $typedData | Out-DataTable
$bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $ConnectionString
$bulkCopy.DestinationTableName = $destTable
$bulkCopy.WriteToServer($csvDataTable)
Содержимое Out-DataTable.ps1 (для будущих читателей)
#######################
function Get-Type {
param($type)
$types = @(
'System.Boolean',
'System.Byte[]',
'System.Byte',
'System.Char',
'System.Datetime',
'System.Decimal',
'System.Double',
'System.Guid',
'System.Int16',
'System.Int32',
'System.Int64',
'System.Single',
'System.UInt16',
'System.UInt32',
'System.UInt64')
if ( $types -contains $type ) {
Write-Output "$type"
}
else {
Write-Output 'System.String'
}
} #Get-Type
#######################
<#
.SYNOPSIS
Creates a DataTable for an object
.DESCRIPTION
Creates a DataTable based on an objects properties.
.INPUTS
Object
Any object can be piped to Out-DataTable
.OUTPUTS
System.Data.DataTable
.EXAMPLE
$dt = Get-psdrive| Out-DataTable
This example creates a DataTable from the properties of Get-psdrive and assigns output to $dt variable
.NOTES
Adapted from script by Marc van Orsouw see link
Version History
v1.0 - Chad Miller - Initial Release
v1.1 - Chad Miller - Fixed Issue with Properties
v1.2 - Chad Miller - Added setting column datatype by property as suggested by emp0
v1.3 - Chad Miller - Corrected issue with setting datatype on empty properties
v1.4 - Chad Miller - Corrected issue with DBNull
v1.5 - Chad Miller - Updated example
v1.6 - Chad Miller - Added column datatype logic with default to string
v1.7 - Chad Miller - Fixed issue with IsArray
.LINK
http://thepowershellguy.com/blogs/posh/archive/2007/01/21/powershell-gui-scripblock-monitor-script.aspx
#>
function Out-DataTable {
[CmdletBinding()]
param([Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)] [PSObject[]]$InputObject)
Begin {
$dt = new-object Data.datatable
$First = $true
}
Process {
foreach ($object in $InputObject) {
$DR = $DT.NewRow()
foreach ($property in $object.PsObject.get_properties()) {
if ($first) {
$Col = new-object Data.DataColumn
$Col.ColumnName = $property.Name.ToString()
if ($property.value) {
if ($property.value -isnot [System.DBNull]) {
$Col.DataType = [System.Type]::GetType("$(Get-Type $property.TypeNameOfValue)")
}
}
$DT.Columns.Add($Col)
}
if ($property.Gettype().IsArray) {
$DR.Item($property.Name) = $property.value | ConvertTo-XML -AS String -NoTypeInformation -Depth 1
}
else {
$DR.Item($property.Name) = $property.value
}
}
$DT.Rows.Add($DR)
$First = $false
}
}
End {
Write-Output @(, ($dt))
}
} #Out-DataTable