【问题标题】:How to get columns Primary key constraints using SqlConnection.GetSchema()如何使用 SqlConnection.GetSchema() 获取列主键约束
【发布时间】:2011-08-16 12:31:23
【问题描述】:

我有一些 ADO.NET 代码来动态检测数据库架构,我需要的是如何使用 SqlConnection 上的 GetSchema 方法获取唯一列约束和主键约束。这是我的代码:

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

【问题讨论】:

    标签: c# stored-procedures ado.net sql-server-2000 database-schema


    【解决方案1】:

    在对GetSchemaTable on SqlConnection 的调用中没有任何内容可以让您弄清楚这一点。

    您可能似乎可以使用IsKey 列值,对于有助于唯一标识表中记录的任何内容,它都应该返回true。但是,来自IsKey 列的文档(强调我的):

    true :该列是一组中的一个 行集中的列,采取 一起,唯一地标识该行。 IsKey 设置为的列集 true 必须唯一标识行 行集。没有要求 这组列是最小的 列集。这组列 可以从基表生成 主键、唯一约束或 唯一索引

    因此,您不能保证它对主键本身有贡献。

    现在,如果您只需要唯一标识行的东西,那么IsKey 就可以了,因为主键并不总是唯一标识行的方法(例如,您可以使用具有唯一索引的自然标识符) .即使您有一个主键和一个包含其他列的唯一索引,所有这些列组合起来的值也将始终是唯一的。

    但是,如果您特别需要查看构成主键的列,那么GetSchemaTable 不会为您提供所需的信息。相反,您可以调用sp_pkeys 系统存储过程来查找有助于生成主键的列的名称。

    【讨论】:

    • 感谢您的回复。从您的解释中,我不明白我需要对上面的 C# 语法进行哪些更改。请您说出我需要对我的代码进行哪些更改。谢谢
    • @shamim:请参阅sp_keys 存储过程的链接,您必须调用此存储过程来获取构成表主键的列。
    • 在我上面的语法中,我使用 sp_keys 过程,在那里我传递了表名,在我的数据表中,我得到了模式,但从模式中我无法检测到主键。所以我寻求你的建议和帮助。谢谢
    • 我不喜欢使用 .SqlDataAdapter da = new SqlDataAdapter(); da.SelectCommand = "sp_pKeys "+tableName;数据表 dtGet = 新数据表(); da.Fill(dtGet); return dtGet;................我想按照上面的描述进行检索。
    • @shamim:为什么不使用SqlCommand,其中CommandTypeCommandType.StoredProcedure,将CommandText 设置为sp_keys,然后将参数添加到Parameters 属性上SqlCommand。然后您可以致电ExecuteDataTable(或ExecuteDataReader 获取结果)。
    【解决方案2】:

    如果仍然有人需要解决方案,我为此创建了一个函数,Sqlcommand 包含您要获取架构信息的语句。

    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
    

    【讨论】:

      【解决方案3】:

      您可以获得primaryKeysUniqueKeysForeignKeys以及此命令返回的dataTable中列出的任何其他架构:"connection.GetSchema (" MetaDataCollections ")"

      下面是返回primaryKeys和UniqueKeys(键名和列名)的代码。

      查看所有文档Here

          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
          }
      

      【讨论】:

        【解决方案4】:

        在 SqlConnection 上调用 GetSchema() 怎么样?使用 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"]);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-29
          • 1970-01-01
          • 2015-11-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多