Как получить столбцы Ограничения первичного ключа с помощью SqlConnection.GetSchema () - PullRequest
7 голосов
/ 01 мая 2011

У меня есть некоторый код ADO.NET для динамического определения схемы базы данных, мне нужно, как получить ограничения уникальных столбцов и ограничения Первичного ключа, используя метод GetSchema в SqlConnection. Вот код, который у меня есть:

conn.Open();     
SqlCommand mSqlCommand = new SqlCommand("sp_pkeys", conn);
mSqlCommand.CommandType = CommandType.StoredProcedure;
mSqlCommand.Parameters.Add(
    "@table_name", SqlDbType.NVarChar).Value = tableName;
SqlDataReader mReader = mSqlCommand.ExecuteReader(
    (CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly));
//ExecuteReader();
DataTable schema = mReader.GetSchemaTable();
mReader.Close();
conn.Close();

Ответы [ 4 ]

6 голосов
/ 01 мая 2011

В вызове GetSchemaTable на SqlConnection нет ничего, что позволило бы вам выяснить это.

Может показаться , что вы можетеиспользуя значение столбца IsKey, которое должно возвращать true для всего, что способствует уникальной идентификации записи в таблице.Однако из документации для столбца IsKey (выделено мной):

true: столбец является одним из набора столбцов в наборе строк, которые вместе взятые однозначно идентифицируют строку.Набор столбцов с IsKey, установленным в true, должен однозначно идентифицировать строку в наборе строк.Не требуется, чтобы этот набор столбцов был минимальным набором столбцов.Этот набор столбцов может быть сгенерирован из первичного ключа базовой таблицы, уникального ограничения или уникального индекса .

Из-за этого вы не можете гарантировать, что он способствуетсам по себе первичный ключ.

Теперь, если все, что вам нужно, это что-то для уникальной идентификации строки, то IsKey подойдет, поскольку первичный ключ не всегда является способом уникальной идентификации строки (например,Вы можете иметь естественные идентификаторы с уникальным индексом).Даже если у вас есть первичный ключ и уникальный индекс с другими столбцами, значения всех этих столбцов в комбинации всегда будут уникальными.

Однако, если вам особенно нужно взглянуть на столбцы, составляющие основнойключ, то GetSchemaTable не даст вам необходимую информацию.Вместо этого вы можете просто вызвать системную хранимую процедуру sp_pkeys, чтобы найти имена столбцов, которые способствуют созданию первичного ключа.

3 голосов
/ 27 апреля 2012

Если кому-то все еще нужны решения, для которых я создал функцию, команда Sql содержит оператор, который вы хотите получить информацию о схеме.

Public Shared Function TableFromCommand(ByVal Command As SqlCommand) As DataTable

    Dim Cn As SqlConnection = Nothing
    Dim Dt As DataTable
    Dim Dr As SqlDataReader
    Dim Column As DataColumn
    Dim Answer As New DataTable

    Try
        Answer.TableName = "SearchTable"
        Cn = New SqlConnection("Your connection string")
        Cn.Open()

        Command.Connection = Cn
        For Each Prm As SqlParameter In Command.Parameters
            If Prm.Direction = ParameterDirection.Input _
            OrElse Prm.Direction = ParameterDirection.InputOutput Then
                Prm.Value = DBNull.Value
            End If
        Next

        Dr = Command.ExecuteReader(CommandBehavior.SchemaOnly Or CommandBehavior.KeyInfo)
        Dt = Dr.GetSchemaTable
        Dim Keys As New List(Of DataColumn)
        Dim ColumnsDic As New SortedDictionary(Of Integer, DataColumn)

        For Each Row As DataRow In Dt.Rows
            Column = New DataColumn
            With Column
                .ColumnName = Row("ColumnName").ToString
                .DataType = Type.GetType(Row("DataType").ToString)
                .AllowDBNull = CBool(Row("AllowDBNull"))
                .Unique = CBool(Row("IsUnique"))
                .ReadOnly = CBool(Row("IsReadOnly"))

                If Type.GetType(Row("DataType").ToString) Is GetType(String) Then
                    .MaxLength = CInt(Row("ColumnSize"))
                End If

                If CBool(Row("IsIdentity")) = True Then
                    .AutoIncrement = True
                    .AutoIncrementSeed = -1
                    .AutoIncrementStep = -1
                End If

                If CBool(Row("IsKey")) = True Then
                    Keys.Add(Column)
                End If
            End With

            ColumnsDic.Add(CInt(Row("ColumnOrdinal")), Column)

            Answer.Columns.Add(Column)
        Next

        If Keys.Count > 0 Then
            Answer.Constraints.Add("PrimaryKey", Keys.ToArray, True)
        End If
    Catch ex As Exception
        MyError.Show(ex)
    Finally
        If Cn IsNot Nothing AndAlso Not Cn.State = ConnectionState.Closed Then
            Cn.Close()
        End If
    End Try

    Return Answer

End Function
1 голос
/ 12 сентября 2015

Вы можете получить primaryKeys, UniqueKeys и ForeignKeys и любую другую схему, указанную в таблице данных, возвращаемой этой командой: "connection.GetSchema (" MetaDataCollections ")"

Ниже кода, который возвращает вам primaryKeys и UniqueKeys (имя ключа и имя столбца).

Смотрите всю документацию Здесь

    public void Dotransfer()
    {
        var sourceSchema = new TableSchema(SourceConnectionString);

    }



  public class TableSchema
    {
        public TableSchema(string connectionString)
        {
            this.TableList = new List<string>();
            this.ColumnList = new List<Columns>();
            this.PrimaryKeyList = new List<PrimaryKey>();
            this.ForeignKeyList = new List<ForeignKey>();
            this.UniqueKeyList = new List<UniqueKey>();

            GetDataBaseSchema(connectionString);

        }

        public List<string> TableList { get; set; }
        public List<Columns> ColumnList { get; set; }
        public List<PrimaryKey> PrimaryKeyList { get; set; }
        public List<UniqueKey> UniqueKeyList { get; set; }
        public List<ForeignKey> ForeignKeyList { get; set; }


        protected void GetDataBaseSchema(string ConnectionString)
        {
            using (SqlConnection connection = new SqlConnection(ConnectionString))
            {

                System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
                builder.ConnectionString = ConnectionString;
                string server = builder.DataSource;
                string database = builder.InitialCatalog;

                connection.Open();


                DataTable schemaTables = connection.GetSchema("Tables");

                foreach (System.Data.DataRow rowTable in schemaTables.Rows)
                {
                    String tableName = rowTable.ItemArray[2].ToString();
                    this.TableList.Add(tableName);

                    string[] restrictionsColumns = new string[4];
                    restrictionsColumns[2] = tableName;
                    DataTable schemaColumns = connection.GetSchema("Columns", restrictionsColumns);

                    foreach (System.Data.DataRow rowColumn in schemaColumns.Rows)
                    {
                        string ColumnName = rowColumn[3].ToString();
                        this.ColumnList.Add(new Columns(){TableName= tableName, FieldName = ColumnName});
                    }

                    string[] restrictionsPrimaryKey = new string[4];
                    restrictionsPrimaryKey[2] = tableName;
                    DataTable schemaPrimaryKey = connection.GetSchema("IndexColumns", restrictionsColumns);


                    foreach (System.Data.DataRow rowPrimaryKey in schemaPrimaryKey.Rows)
                    {
                        string indexName = rowPrimaryKey[2].ToString();

                        if (indexName.IndexOf("PK_") != -1)
                        {
                            this.PrimaryKeyList.Add(new PrimaryKey()
                            {
                                TableName = tableName,
                                FieldName = rowPrimaryKey[6].ToString(),
                                PrimaryKeyName = indexName
                            });
                        }

                        if (indexName.IndexOf("UQ_") != -1)
                        {
                            this.UniqueKeyList.Add(new UniqueKey()
                            {
                                TableName = tableName,
                                FieldName = rowPrimaryKey[6].ToString(),
                                UniqueKeyName = indexName
                            });
                        }

                    }


                    string[] restrictionsForeignKeys = new string[4];
                    restrictionsForeignKeys[2] = tableName;
                    DataTable schemaForeignKeys = connection.GetSchema("ForeignKeys", restrictionsColumns);


                    foreach (System.Data.DataRow rowFK in schemaForeignKeys.Rows)
                    {

                        this.ForeignKeyList.Add(new ForeignKey()
                        {
                            ForeignName = rowFK[2].ToString(),
                            TableName = tableName,
                            // FieldName = rowFK[6].ToString() //There is no information
                        });                
                    }


                }


            }

        }

    }    

    public class Columns
    {
        public string TableName { get; set; }
        public string FieldName { get; set; }
    }

    public class PrimaryKey
    {
        public string TableName { get; set; }
        public string PrimaryKeyName { get; set; }
        public string FieldName { get; set; }
    }


    public class UniqueKey
    {
        public string TableName { get; set; }
        public string UniqueKeyName { get; set; }
        public string FieldName { get; set; }
    }

    public class ForeignKey
    {
        public string TableName { get; set; }
        public string ForeignName { get; set; }
       // public string FieldName { get; set; } //There is no information
    }
0 голосов
/ 04 марта 2014

А как насчет вызова GetSchema () для вашего SqlConnection?Используя collectionName="IndexColumns" и список ограничений схемы, вы можете запросить необходимую информацию с помощью GetSchema ().

См .:

Как только я установил SqlConnection, используя имя базы данных, у меня сработало следующее:

var connectionString = 
    string.Format("Server=.\\SQLEXPRESS;Database={0};Trusted_Connection=true", dbName);
using (var sqlConnection = new SqlConnection(connectionString))
{
    sqlConnection.Open();
    DataTable tables = sqlConnection.GetSchema("Tables");
    foreach (DataRow tablesRow in tables.Rows)
    {
        string tableName = tablesRow["table_name"].ToString();
        Console.WriteLine(tableName);
        var indexCols = sqlConnection.GetSchema("IndexColumns",
            new string[] {dbName, null, tableName, "PK_" + tableName, null});
        foreach (DataRow indexColsRow in indexCols.Rows)
            Console.WriteLine("  PK: {0}", indexColsRow["column_name"]);
    }
}
...