Tại sao C # SMO không thể thấy các thuộc tính mở rộng trên một cột nhưng Powershell SMO có thể?


7

Tôi đang cố đọc các thuộc tính mở rộng trên các bảng và cột trong ứng dụng C # winforms. Tôi đang sử dụng SQL Server SMO để làm như vậy. Khi tôi thực thi ứng dụng, nó không thấy các thuộc tính mở rộng, nhưng khi tôi đọc các thuộc tính mở rộng bằng PowerShell, nó sẽ thấy các thuộc tính mở rộng.

Mã C #:

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

Mã 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

Tôi đã kiểm tra và cả Visual Studio và PowerShell đều đang sử dụng cùng một phiên bản SMO (11.0.0.0). Khi tôi thực thi mã C #, col.ExtendsProperIES.Count = 0, nhưng khi tôi thực thi mã PowerShell, tôi nhận được:

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

Có ai có bất kỳ ý tưởng về lý do tại sao điều này có thể xảy ra?

thông tin thêm

Trong mã C #, tôi mở DataReader trên bảng bằng cách sử dụng:

sourceServer.ConnectionContext.ExecuteReader(<select command>)

để lấy dữ liệu từ bảng. Sau đó tôi đi vào một vòng lặp while với DataReader và bên trong vòng lặp while đó tôi có:

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

Khi tôi bước qua foreach, sourceTablebiến có thuộc tính mở rộng của nó, nhưng colbiến cột thì không.


Wayne, bạn đã chạy SQL Server Profiler hay Extended Events, để nắm bắt những truy vấn nào đang được SMO thực hiện trong từng trường hợp chưa? Sẽ rất hữu ích nếu biết các truy vấn đang được SMO thực thi thông qua PowerShell, hoặc không, được thực hiện khi chạy qua C #. Nó cũng thực sự có ích khi thấy một số mã thực tế được đăng trong câu hỏi (không phải trong một bình luận ở đây) vì tôi tò mò nếu bạn đang kết nối chính xác theo cách tương tự trong mỗi trường hợp.
Solomon Rutzky

Câu trả lời:


2

Tôi chỉ muốn làm bóng @BradC một chút. Tôi đã kiểm tra mã của anh ấy trên Visual Studio 2015 (Bản cập nhật 3) trên máy Windows 10 Pro x64 dựa trên phiên bản SQL Server 2014 và tôi có thể xác nhận bạn có thể nhận được Thuộc tính mở rộng của một trường mà không gặp sự cố.

Để nhân rộng tôi sử dụng một trong những cơ sở dữ liệu địa phương của tôi. Tôi đã sử dụng đoạn mã sau để xác định một số thuộc tính mở rộng.

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

Tôi đã tạo một dự án giao diện điều khiển mới và thêm các tài liệu tham khảo sau:

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

Tất cả từ:

\% Cài đặt đường dẫn% \ Microsoft SQL Server \ 130 \ SDK \ Assemblies \

Vì vậy, toàn bộ mã của tôi, dựa trên @ BradC trông giống như:

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

nhập mô tả hình ảnh ở đây

Tất nhiên bây giờ bạn có thể truy cập các thuộc tính và sử dụng các giá trị của chúng.

Giá trị Count không hoạt động trên ví dụ của bạn:

nhập mô tả hình ảnh ở đây


1

Bạn đã không hiển thị mã của mình để khởi tạo colđối tượng, chúng ta có thể xem mã đó không?

Sử dụng một cái gì đó như GetSchemaTable()phương thức của nhà cung cấp dữ liệu sẽ không thực sự trả về đối tượng bảng (SQL SMO) thực tế , nó trả về một bảng mới có nhiều thuộc tính cột hữu ích, nhưng (theo như tôi có thể thấy) không bao gồm các thuộc tính mở rộng.

Hãy xem câu trả lời StackOverflow này của Christopher Klein . Nếu tôi đang đọc đúng, điều đó sẽ trả về một đối tượng bảng SQL SMO thực tế , mà tôi nghĩ sẽ cho phép bạn truy xuất các thuộc tính cột mở rộng, đại loại như:

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

Nếu điều đó không hiệu quả, chỉ cần sử dụng phiên bản PowerShell đang hoạt động của bạn hoặc sử dụng một trong những ý tưởng khác trong câu trả lời liên quan này .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.