Warum kann C # SMO keine erweiterten Eigenschaften in einer Spalte sehen, Powershell SMO jedoch?

7

Ich versuche, erweiterte Eigenschaften für Tabellen und Spalten in einer Winforms C # -Anwendung zu lesen. Ich verwende dazu SQL Server SMO. Wenn ich die Anwendung ausführe, werden die erweiterten Eigenschaften nicht angezeigt. Wenn ich jedoch die erweiterten Eigenschaften mit PowerShell lese, werden die erweiterten Eigenschaften angezeigt.

Der C # -Code:

var x = col.ExtendedProperties.Count;
var NPI = col.ExtendedProperties["NPI"].Value;
bool npi = bool.Parse(NPI.ToString());

Der PowerShell-Code:

Add-Type -AssemblyName "Microsoft.SqlServer.Smo, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
$server = New-Object Microsoft.SqlServer.Management.Smo.Server $env:COMPUTERNAME
$server.Databases["<db name>"].Tables["<table name>"].Columns["<column name>"].ExtendedProperties | Select Name, Value, State

Ich habe überprüft, dass sowohl Visual Studio als auch PowerShell dieselbe Version von SMO (11.0.0.0) verwenden. Wenn ich den C # -Code ausführe, ist col.ExtendedProperties.Count = 0, aber wenn ich den PowerShell-Code ausführe, erhalte ich:

Name Value    State
---- -----    -----
NPI  False Existing

Hat jemand eine Idee, warum dies passieren könnte?

zusätzliche Information

Im C # -Code öffne ich einen DataReader für eine Tabelle mit:

sourceServer.ConnectionContext.ExecuteReader(<select command>)

um die Daten aus der Tabelle abzurufen. Ich gehe dann mit DataReader in eine while-Schleife und in dieser while-Schleife habe ich:

foreach (Column col in sourceTable.Columns) 
{ 
StringBuilder cleanData = CleanseColumn(col, dr[col.Name].ToString());
sbvalues.Append("'" + cleanData + "', "); 
}

Wenn ich durch die gehe, hat foreachdie sourceTableVariable ihre erweiterte Eigenschaft, die colSpaltenvariable jedoch nicht.

Wayne E. Pfeffer
quelle
Wayne, haben Sie SQL Server Profiler oder Extended Events ausgeführt, um zu erfassen, welche Abfragen jeweils von SMO ausgeführt werden? Es ist hilfreich zu wissen, ob die von SMO über PowerShell ausgeführten Abfragen ausgeführt werden oder nicht, wenn sie über C # ausgeführt werden. Es wäre auch sehr hilfreich, einen tatsächlichen Code in der Frage zu sehen (nicht in einem Kommentar hier), da ich neugierig bin, ob Sie jeweils genau die gleiche Verbindung herstellen.
Solomon Rutzky

Antworten:

2

Ich möchte @BradC nur ein wenig beschatten. Ich habe seinen Code in Visual Studio 2015 (Update 3) auf einem Windows 10 Pro x64-Computer gegen eine SQL Server 2014-Instanz getestet und kann bestätigen, dass Sie die erweiterten Eigenschaften eines Felds ohne Probleme erhalten können.

Zum Replizieren verwende ich eine meiner lokalen Datenbanken. Ich habe den folgenden Code-Snip verwendet, um einige erweiterte Eigenschaften zu definieren.

USE MyLocalDb;
GO
EXEC sys.sp_addextendedproperty 
@name = N'MS_DescriptionExample', 
@value = N'Some EP example.', 
@level0type = N'SCHEMA', @level0name = dbo, 
@level1type = N'TABLE',  @level1name = tblATableWithAtblPrefix,
@level2type = N'COLUMN', @level2name = Forename;
GO

Ich habe ein neues Konsolenprojekt erstellt und die folgenden Referenzen hinzugefügt:

Microsoft.SqlServer.ConnectionInfo
Microsoft.SqlServer.Management.Sdk.Sfc
Microsoft.SqlServer.Smo
Microsoft.SqlServer.SqlEnum

Alles aus:

\% Installationspfad% \ Microsoft SQL Server \ 130 \ SDK \ Assemblies \

Mein ganzer Code, basierend auf @ BradCs, sieht also so aus:

using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

namespace ConsoleApplication7
{
    class Program
    {
        private static Database database;
        static void Main(string[] args)
        {
            Microsoft.SqlServer.Management.Smo.Server server;

            SqlConnection connection = new SqlConnection("Integrated Security=SSPI; Data Source=SIS_DBA");
            Microsoft.SqlServer.Management.Common.ServerConnection serverConnection = 
                new Microsoft.SqlServer.Management.Common.ServerConnection(connection);

            server = new Server(serverConnection);

            database = server.Databases["ImmigSql"];

            foreach (Table table in database.Tables)
            {
                Console.WriteLine(" " + table.Name);
                foreach (Column col in table.Columns)
                {
                    Console.WriteLine("  " + col.Name + " " + col.DataType.Name);
                    foreach (var property in col.ExtendedProperties)
                    {
                        Console.WriteLine(" " + property.ToString() + "");
                    }
                }
            }
            Console.ReadLine();
        }
    }
}

Geben Sie hier die Bildbeschreibung ein

Natürlich können Sie jetzt auf die Eigenschaften zugreifen und deren Werte verwenden.

Der Count-Wert, der in Ihrem Beispiel nicht funktioniert hat:

Geben Sie hier die Bildbeschreibung ein

Nelz
quelle
1

Sie haben Ihren Code, der das colObjekt instanziiert , nicht angezeigt. Können wir diesen Code sehen?

Wenn Sie so etwas wie die GetSchemaTable()Methode des Datenlesers verwenden, wird das tatsächliche Tabellenobjekt (SQL SMO) nicht zurückgegeben, sondern eine neue Tabelle mit vielen nützlichen Spalteneigenschaften, die jedoch (soweit ich sehen kann) keine erweiterten Eigenschaften enthält.

Schauen Sie sich diese StackOverflow-Antwort von Christopher Klein an . Wenn ich das richtig lese, sollte dies ein tatsächliches SQL SMO-Tabellenobjekt zurückgeben, mit dem Sie meiner Meinung nach erweiterte Spalteneigenschaften abrufen können, etwa:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;


// Add references: (in c:\Program Files\Microsoft SQL Server\90\SDK\Assemblies\)
// Microsoft SqlServer.ConnectionInfo
// Microsoft SqlServer.Management.Sdk.Sfc
// Microsoft SqlServer.Smo

namespace SMO
{
    class Program
    {
        static Database db;

        static void Main(string[] args)
        {
            Microsoft.SqlServer.Management.Smo.Server server;

            SqlConnection sqlConnection = new SqlConnection(@"Integrated Security=SSPI; Data Source=LOCAL");
            //build a "serverConnection" with the information of the "sqlConnection"
            Microsoft.SqlServer.Management.Common.ServerConnection serverConnection =
              new Microsoft.SqlServer.Management.Common.ServerConnection(sqlConnection);

            //The "serverConnection is used in the ctor of the Server.
            server = new Server(serverConnection);

            db = server.Databases["TestDB"];

            Table tbl;
            tbl = db.Tables["Sales"];

            //warning, not tested, your code goes here
            foreach (Column col in tbl.Columns)
            {
               var x = col.ExtendedProperties.Count;
               var NPI = col.ExtendedProperties["NPI"].Value;
               bool npi = bool.Parse(NPI.ToString());
            } 
        }
    }
}

Wenn dies nicht funktioniert, bleiben Sie einfach bei Ihrer funktionierenden PowerShell-Version oder greifen Sie auf eine der anderen Ideen in dieser Antwort zurück .

BradC
quelle