Cataster
Cataster

Reputation: 3521

Why is Enumeration Name property not working?

I have a script that i want to display the connection strings of a database

Import-Module SqlServer
$AS = New-Object Microsoft.AnalysisServices.Server
$AS.connect("server1")

Now if i use the FindByName() property

$db = $AS.Databases.FindByName("database1")
$db.DataSources[0].ConnectionString

I get back the connection string successfully

however if i use Enumerator

foreach ($db in $AS.Databases.GetEnumerator())
{ $dbName = $db.Name
  $dbName
  $dbName.DataSources[0].ConnectionString
}

I get back the database name along with error/exception (because it couldnt get connection string for some reason):

database1

Cannot index into a null array.

database2

Cannot index into a null array.

I tried the following also:

$database1 = "database1"
$database1.DataSources[0].ConnectionString

and i also get back the same exception

So why is it that only FindByName works?

for additional info, this is what GetEnumerator lists:

$AS.Databases.GetEnumerator()

enumerator output

but also $AS.Databases

outputs the same thing...so whats even the point of the enumerator?

gm -i $AS.Databases

gmdb

gm -i $AS.Databases..GetEnumerator()

gmenu

Upvotes: 2

Views: 131

Answers (2)

Cataster
Cataster

Reputation: 3521

PowerShell does its own enumerating.

This done the trick!

foreach ($db in $AS.Databases){
  Write-Hst $db.Name -Fore green
  $db.DataSources | ForEach-Object{$_.ConnectionString}
}

Upvotes: 0

briantist
briantist

Reputation: 47792

Part of what you're seeing is PowerShell's handling of (some) enumerables. Many (most?) are unrolled by PowerShell automatically, so the call to .GetEnumerator() isn't needed.

That's what's happening in your last example, looking at $AS.Databases vs $AS.Databases.GetEnumerator(). But it's only because you sent it out to the pipeline in that case; it's the display process that did the unrolling (in both cases).

If you did gm -i $AS.Databases vs gm -i $AS.Databases.GetEnumerator() you're going to see the difference; same if you assigned each of those to a variable and tried to call methods on them.

But back to using foreach it should again be redundant: foreach ($db in $AS.Databases) should work the same as foreach ($db in $AS.Databases.GetEnumerator()) but I don't have this type in my env right now to test that.

So back to the issue at hand inside the foreach, I suggest you start checking types again. Compare:

$db = $Analysis_Server.Databases.FindByName("database1")
gm -i $db

to

foreach ($db in $AS.Databases.GetEnumerator())
{ 
    gm -i $db
    break
}

You might find the types aren't what you think.

This is especially true because you're using dot . notation, because PowerShell has another array shortcut built-in since version 3, whereby you can use . on an array of types, to return an array of the .Property of each item. For example:

$p = Get-Process chrome  # choose your own adventure
$p.Count
$p[0].Name
$p.Name

So a property you thought you were accessing on a single object, may have been on an array of objects, and may have been returning an array (or a single object), and handing that in the foreach may have returned a different quantity, or something, resulting in your attempt to index into what used to be an array, no longer work.

But again it's speculation on my part because I don't have those objects. Hopefully this helps you dig deeper into it though.

Upvotes: 2

Related Questions