Closed petervandivier closed 1 month ago
If you think it's an issue with SqlBulkCopy - why don't you open an issue against SqlBulkCopy? As you have shown, there is nothing dbatools can do here.
I don't believe that I've demonstrated there is nothing to be done. A cursory glance at the SqlBulkCopy source code seems to imply that GUID support exists (it would be a little shocking if it didn't).
While I am unable at this time to parse out where the root cause exists, I'll be happy to open up an issue against either the SqlBulkCopy source or docs pages as and when the time seems ripe to do so.
Even assuming SqlBulkCopy must be modified at source to support GUID target types, I imagine the lack of support demonstrated in this issue might warrant the addition of a unit test on resolution.
My last comment was maybe too short.
I don't see a quick fix. And I don't have time to do deeper investigations. So if you have the time and a solution, I would be happy to include it in the dbatools source code.
But maybe in the future, some other contributor can take the time and come up with a solution.
if bulkcopy didn't support GUIDs there would be zillions of users ranting. I think the culprit here is that we use an external lib (Lumen) to read the csv, and that doesn't output a guid column, rather a varchar one.
Idk, there appears to exist a GUID unit test in the LumenWorks source :thinking:
namespace LumenWorks.Framework.Tests.Unit.IO.Csv
{
[TestFixture]
public class ColumnTests
{
[Test]
public void ConvertGuid()
{
var expected = Guid.NewGuid();
var column = new Column { Name = "A", Type = typeof(Guid) };
var candidate = column.Convert(expected.ToString());
Assert.IsInstanceOf<Guid>(candidate);
Assert.That(expected == (Guid)candidate);
}
and what tells lumen to use a guid column when reading ? it doesn't do heuristic AFAIK, so we know that lumen supports guid, but IMHO we're not telling via Import-DbaCsv (again, AFAIK, we support playing with column mapping via NAME, nothing via TYPE) that a guid column is needed when reading the csv.
BTW, definitely related to https://github.com/dataplat/dbatools/issues/8409 as noted in the issue, it's the same exact deal (in that case, we're not telling Lumen to output a bit, in this we're not telling Lumen to output a guid)
so, ideally, fixable. I'll work on this and report back if there are further limitations
we know that lumen supports guid, but IMHO we're not telling via Import-DbaCsv
This condition pops if-and-only-if we're inserting to a pre-existing table. At first thought a schema check would allow mapping of this sort.
Since it's not been reported before it seems like a potentially niche condition (based on only 2 reports in 2 years), perhaps this case is low-occurrence enough that it's prudent to save the schema check for a catch{}
block if one of the known errors pops so we avoid the overhead for runs where it doesn't matter
when the table gets autocreated all columns are nvarchar(max) so it's easy :D
I did not forget about this, something that seemed like a 50LOC update is turning into a 500LOC one. I need to play a bit with lumen's API (fortunately there are examples to follow) directly in c# to figure out how to make it work on PS.
@rezanid , @petervandivier , would you give #9479 a look, and maybe try that code as well ?
Verified issue does not already exist?
I have searched and found no existing issue
What error did you receive?
No obvious quick fix jumps out at me reading through the SqlBulkCopy docs at this time.
Possibly related: #8409
Steps to Reproduce
It appears that the
SqlBulkCopy
object as currently defined inInvoke-DbaCsv
does not support inserting valid guid strings into auniqueidentifier
target column.The below repro errors out:
I tried to step through the source code to see if there was something obvious I was missing about this functionality. Extracting just the relevant code for a minimal repro appears to indicate that this may be an underlying issue with
SqlBulkCopy
SqlBulkCopy repro initialisation
```powershell $server = Connect-DbaInstance -SqlInstance localhost -Database tempdb $sqlconn = $server.ConnectionContext.SqlConnectionObject if ($sqlconn.State -ne 'Open') {$sqlconn.Open()} # Import-DbaCsv.ps1#L540 # [int]$bulkCopyOptions = ([Microsoft.Data.SqlClient.SqlBulkCopyOptions]::Default) # $bulkcopy = New-Object Microsoft.Data.SqlClient.SqlBulkCopy( # $sqlconn, # $bulkCopyOptions, # $transaction # $null # ) # # New-Object: Cannot find an overload for "SqlBulkCopy" and the argument count: 3 $bulkcopy = New-Object Microsoft.Data.SqlClient.SqlBulkCopy($sqlconn) $bulkcopy.DestinationTableName = 'foo' $bulkcopy.BulkCopyTimeout = 0 $bulkCopy.BatchSize = 100 $bulkCopy.NotifyAfter = 30000 $bulkCopy.EnableStreaming = $true $stream = [System.IO.File]::OpenRead("foo.csv") $textReader = New-Object System.IO.StreamReader( $stream, [System.Text.Encoding]::"UTF8" ) $FirstRowHeader = $true $Delimiter = "," $Quote = '"' $Escape = '"' $Comment = '#' $TrimmingOption = "None" $BufferSize = 4096 $reader = New-Object LumenWorks.Framework.IO.Csv.CsvReader( $textReader, $FirstRowHeader, $Delimiter, $Quote, $Escape, $Comment, [LumenWorks.Framework.IO.Csv.ValueTrimmingOptions]::$TrimmingOption, $BufferSize, $NullValue # $null ) ```After running the above initialisation, executing the below errors out.
Please confirm that you are running the most recent version of dbatools
v2.1.15
- May 18, 2024Other details or mentions
Slack channel chat context: https://sqlcommunity.slack.com/archives/C1M2WEASG/p1721846945371649
What PowerShell host was used when producing this error
VS Code (integrated terminal)
PowerShell Host Version
SQL Server Edition and Build number
.NET Framework Version
.NET 8.0.6