為什麼 C# SMO 看不到列上的擴展屬性,但 Powershell SMO 可以?
我正在嘗試讀取 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 版本,或訴諸此相關答案中的其他想法之一。