Sql-Server

為什麼 C# SMO 看不到列上的擴展屬性,但 Powershell SMO 可以?

  • August 13, 2017

我正在嘗試讀取 winforms C# 應用程序中表和列的擴展屬性。我正在使用 SQL Server SMO 來執行此操作。當我執行應用程序時,它看不到擴展屬性,但是當我使用 PowerShell 讀取擴展屬性時,它確實看到了擴展屬性。

C# 程式碼:

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

PowerShell 程式碼:

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

我檢查過,Visual Studio 和 PowerShell 都使用相同版本的 SMO (11.0.0.0)。當我執行 C# 程式碼時 col.ExtendedProperties.Count = 0,但是當我執行 PowerShell 程式碼時,我得到:

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

有沒有人知道為什麼會發生這種情況?

附加資訊

在 C# 程式碼中,我使用以下方法在表上打開 DataReader:

sourceServer.ConnectionContext.ExecuteReader(<select command>)

從表中檢索數據。然後我使用 DataReader 進入一個 while 循環,在這個 while 循環中我有:

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

當我單步執行foreach時,sourceTable變數具有擴展屬性,但col列變數沒有。

我只是想稍微影響一下@BradC。我在 Windows 10 Pro x64 機器上針對 SQL Server 2014 實例在 Visual Studio 2015(更新 3)上測試了他的程式碼,我可以確認您可以毫無問題地獲得欄位的擴展屬性。

為了複製,我使用我的本地數據庫之一。我使用以下程式碼片段來定義一些擴展屬性。

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

我創建了一個新的控制台項目並添加了以下引用:

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

全部來自:

%安裝路徑%\Microsoft SQL Server\130\SDK\Assemblies\

所以我的整個程式碼,基於@BradC’s 看起來像:

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();
       }
   }
}

在此處輸入圖像描述

當然,您現在可以訪問屬性並使用它們的值。

不適用於您的範例的 Count 值:

在此處輸入圖像描述

您還沒有顯示實例化col對象的程式碼,我們可以看到該程式碼嗎?

使用類似 datareader 的GetSchemaTable()方法實際上不會返回實際的(SQL SMO)表對象,它會返回一個具有許多有用列屬性的新表,但是(據我所知)不包括擴展屬性。

看看 Christopher Klein 的這個 StackOverflow 答案。如果我沒看錯,那應該返回一個實際的SQL SMO 表對象,我認為它可以讓您檢索擴展的列屬性,例如:

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());
           } 
       }
   }
}

如果這不起作用,請堅持使用您的工作 PowerShell 版本,或訴諸此相關答案中的其他想法之一

引用自:https://dba.stackexchange.com/questions/168681