0 votes

Trying to read data from as SQL database and .ExecuteReader() appears to be successful, but while .Read() must be returning False. Please review the code below and explain what might be wrong. Thanks

Here is my code:

Import-Module Adaxes

$databaseHost = "[i]dbHostname[/i]"
$databaseName = "[i]dbName[/i]"
$tableName = "[i]tableName[/i]"
$userIDField = "EMPID"

$databaseUsername = $NULL
$databasePassword = $NULL

# Connect to the database
$connectionString = "Data Source=$databaseHost; Initial Catalog=$databaseName;"
if ($databaseUsername -eq $NULL)
{
    $connectionString = $connectionString + "Integrated Security=SSPI;"
}
else
{
    $connectionString = $connectionString +
        "User ID=$databaseUsername;Password=$databasePassword;"
}

try
{
    $connection = New-Object "System.Data.SqlClient.SqlConnection"  $connectionString
    $connection.Open()

    # Check whether the user exists in the database
    try
    {
        $command = $connection.CreateCommand()
        $command.CommandText = "SELECT EMPID, LASTNAME, FIRSTNAME FROM $tableName WHERE $tableName`.$userIDField = @UserID"
     #   $command.Parameters.Add("@UserID", "%employeeID%") | Out-Null;
        $command.Parameters.Add("@UserID", "500333") | Out-Null;
        $Context.LogMessage($command.CommandText, "Information")
        $reader = $command.ExecuteReader()  
    }
    finally
    {
        # Close the search and release resources
        $command.Dispose()
    }

    if ($reader -eq $NULL)
    {
        $Context.LogMessage("A user with employee ID " + "%employeeID%" + " does not exist in the database", "Warning")
        return # Exit script
    }
    else
    {   $Context.LogMessage("before While", "Information")
       while ($reader.Read()){
           $Context.LogMessage("inside while loop reading records", "Information")
        $empID=$reader.GetString(0)
        $lName=$reader.GetString(1)
        $fName=$reader.GetString(2)
       # $deptNum = $reader.GetString(3)
       $Context.LogMessage( $fName,"Information")
}
    }
}
catch [System.Exception]
{
    $ErrorMessage = $_.Exception.Message
    [string]$LineNumber = $_.InvocationInfo.ScriptLineNumber
    [string]$Offset = $_.InvocationInfo.OffsetInLine
    [string]$errLine = $_.InvocationInfo.Line

    Write-Error $ErrorMessage
    $Context.LogMessage("At Line #: " + $LineNumber + " at char " + $Offset, "Error")
    $Context.LogMessage("Executing: " + $errLine, "Error") 
}
    finally
    {
        # Close the database connection and release resources
        $command.Dispose()
    $connection.Close()
}
by (270 points)

1 Answer

0 votes
by (216k points)
selected by
Best answer

Hello,

The thing is that an instance of the SqlDataReader class represented by the $reader variable exposes the MoveNext iterator. It is used to enumerate the records returned by the database. When you call the $reader variable on this line:

if ($reader -eq $NULL)

this forces PowerShell to enumerate all members of the $reader SqlDataReader class (i.e. properties, methods). When doing so, it also enumerates all records returned by the database and moves the MoveNext iterator to the very last line returned by the database. When you further call the $reader.Read() method, it also tries to call MoveNext, but since it is already the last record, there is nowhere to move further. This is where the error occurs.

Here's an updated script that resolves the issue:

$databaseHost = "[i]dbHostname[/i]"
$databaseName = "[i]dbName[/i]"
$tableName = "[i]tableName[/i]"
$userIDField = "EMPID"

$databaseUsername = $NULL
$databasePassword = $NULL

# Connect to the database
$connectionString = "Data Source=$databaseHost; Initial Catalog=$databaseName;"
if ($databaseUsername -eq $NULL)
{
    $connectionString = $connectionString + "Integrated Security=SSPI;"
}
else
{
    $connectionString = $connectionString +
        "User ID=$databaseUsername;Password=$databasePassword;"
}

try
{
    $connection = New-Object "System.Data.SqlClient.SqlConnection"  $connectionString
    $connection.Open()

    # Check whether the user exists in the database
    $command = $connection.CreateCommand()
    $command.CommandText = "SELECT EMPID, LASTNAME, FIRSTNAME FROM $tableName WHERE $tableName`.$userIDField = @UserID"
    # $command.Parameters.Add("@UserID", "%employeeID%") | Out-Null;
    $command.Parameters.Add("@UserID", "500333") | Out-Null;
    $Context.LogMessage($command.CommandText, "Information")
    $reader = $command.ExecuteReader()

    if ($reader.Read())
    {
        $empID=$reader.GetString(0)
        $lName=$reader.GetString(1)
        $fName=$reader.GetString(2)
        # $deptNum = $reader.GetString(3)
        $Context.LogMessage( $fName,"Information")
    }
    else
    {
        $Context.LogMessage("A user with employee ID " + "%employeeID%" + " does not exist in the database", "Warning")
        return # Exit script
    }
}
catch [System.Exception]
{
    $ErrorMessage = $_.Exception.Message
    [string]$LineNumber = $_.InvocationInfo.ScriptLineNumber
    [string]$Offset = $_.InvocationInfo.OffsetInLine
    [string]$errLine = $_.InvocationInfo.Line

    Write-Error $ErrorMessage
    $Context.LogMessage("At Line #: " + $LineNumber + " at char " + $Offset, "Error")
    $Context.LogMessage("Executing: " + $errLine, "Error")
}
finally
{
    # Close the database connection and release resources
    if ($reader) { $reader.Close() }
    if ($command) { $command.Dispose() }
    if ($connection) { $connection.Close() }
}

Related questions

0 votes
0 answers

Is it possible to query the external SQL database for audits of a specific action, even if that action is a 'sub-command' of a business rule, scheduled task etc? Simple ... interested if data is structured in the log in a manner that would allow this? Thanks

asked Aug 30, 2014 by firegoblin (1.6k points)
0 votes
1 answer

We have a need to restore and read audit logs from a backup. We have restored the backup but are looking for guidance on the easiest method to access logs within this file. Thanks in advance!

asked Nov 22, 2016 by VTPatsFan (610 points)
0 votes
1 answer

Hi, Is there a simple way to read the Exchange AD attributes without having to use the custom Exchange ADSI interface API? I'm trying to write an Adaxes Scheduled Task ... Limit") - other than the fact that the command doesn't recognise the property! Thanks

asked Aug 19, 2015 by firegoblin (1.6k points)
0 votes
1 answer

Hi Everyone We have 3 Adaxes services set up around the globe and followed the MS SQL replication how-to (https://www.adaxes.com/help/EnableDatabaseReplication/) to then ... use their local SQL server and make use of the SQL replication setup? Thanks, Felix

asked Jul 24 by felix (150 points)
0 votes
1 answer

Short question: I have a Powershell script that is generating some information and saving it to a SQL table. Is there some way to save that information into a field in AD ... using Adaxes, but I don't know how to go the opposite way basically. Thanks!

asked Mar 12 by cstaub (100 points)
3,548 questions
3,239 answers
8,232 comments
547,814 users