繁体   English   中英

如何获取ADO.NET中的主键列?

[英]How do I get the primary key columns in ADO.NET?

我有一张桌子:

CREATE TABLE [dbo].[DeliveryData](
    [DeliveryId] [int] IDENTITY(1,1) NOT NULL,
   ...
CONSTRAINT [PK_DeliveryData] PRIMARY KEY CLUSTERED 
(
    [DeliveryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

和代码:

public void GetPrimaryKeyColumns(SqlConnection conn) {
    SqlCommand cmd = conn.CreateCommand();
    cmd.CommandText = "select * from [dbo].[DeliveryData]";
    SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly);
    DataTable schema = reader.GetSchemaTable();
    DataColumn[] columns = schema.PrimaryKey;
    ...
}

cmd,阅读器和架构都看起来不错,但是列的长度为零。 它不应该包含“ DeliveryId”吗? 如何获得主列“ DeliveryId”?

谢谢您的帮助!

布莱克

模式表不是DeliveryData表。 您必须检查IsKey true的架构表,然后获取ColumnName字段。 然后,您可以使用它在常规数据表上找到真实列。

更新

GetSchemaTable()返回元数据信息的数据表,您可以在文档中查看: https : //msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqldatareader.getschematable(v=vs.110) .aspx

如果要运行查询,返回的数据表中的行最终将与查询中的列数一样多。 这是我从数据库中的测试表获得的模式表的部分屏幕截图。 注意,每一列现在都是一行,IsKey字段会告诉您该列是否为键列: 在此处输入图片说明

如果要在DataTable上使用PrimaryKey属性,请不要使用GetSchemaTable() ,只需使用SqlDataAdapter填充常规DataTable。

更新2

使用CommandBehavior.KeyInfo代替CommandBehavior.SchemaOnly

使用SMO

using Microsoft.SqlServer.Management.Smo;
....

Server svr = new Server("Your Server Name");
Database db = svr.Databases["Your Database Name"];
Table tbl = db.Tables["DeliveryData"];
foreach (Column c in tbl.Columns)
{
    bool isAKeyColumn = c.InPrimaryKey

}

在所有情况下,使用GetSchemaTable,MSSQL都不会返回正确的主键信息。 (不足为奇。例如,几乎所有数据库供应商都比MS更好地支持ODBC。)但是,以下查询确实起作用:

SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as  kcu
    ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
    AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
    AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
    AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG
    AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
    AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
    AND tc.TABLE_SCHEMA = 'dbo'
    AND tc.TABLE_NAME = 'DeliveryData'
ORDER BY ORDINAL_POSITION;

这是一个完整的解决方案:

public List<string> GetPrimaryKeyColumns(DbConnection conn, string schema, string table) {
    DbCommand cmd = conn.CreateCommand();

    DbParameter p = cmd.CreateParameter();
    p.ParameterName = "@schema";
    p.Value = schema;
    p.DbType = DbType.String; 
    p.Direction = ParameterDirection.Input;
    cmd.Parameters.Add(p);

    p = cmd.CreateParameter();
    p.ParameterName = "@table";
    p.Value = table;
    p.DbType = DbType.String;
    p.Direction = ParameterDirection.Input;
    cmd.Parameters.Add(p);

    cmd.CommandText = @"SELECT kcu.COLUMN_NAME
                        FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
                        LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as  kcu
                            ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
                               AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
                               AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
                               -- AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG  doesn't work on MySQL
                               AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
                               AND kcu.TABLE_NAME = tc.TABLE_NAME
                        WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
                              AND tc.TABLE_SCHEMA = @schema
                              AND tc.TABLE_NAME = @table
                        ORDER BY ORDINAL_POSITION";

    DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo);

    List<string> res = new List<string>();
    while (reader.Read()) {
        var str = reader[0];
        if (str != System.DBNull.Value)
            res.Add((string) str);
    }
    reader.Dispose();
    cmd.Dispose();
    return res;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM