Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过GetSchema确定主键列_C#_.net_Tsql_Ado.net - Fatal编程技术网

C# 通过GetSchema确定主键列

C# 通过GetSchema确定主键列,c#,.net,tsql,ado.net,C#,.net,Tsql,Ado.net,是否有一种方法可以使用ADO.NETGetSchema方法确定列是否为主键 以下是到目前为止我得到的信息: public IEnumerable<DbColumnInfo> GetColumns(string providerName, string connectionString, string tableName) { DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);

是否有一种方法可以使用ADO.NET
GetSchema
方法确定列是否为主键

以下是到目前为止我得到的信息:

public IEnumerable<DbColumnInfo> GetColumns(string providerName, string connectionString, string tableName)
{
    DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
    using (DbConnection connection = factory.CreateConnection())
    using (DbCommand command = factory.CreateCommand())
    {
        connection.ConnectionString = connectionString;
        connection.Open();
        command.Connection = connection;

        var columns = connection.GetSchema("Columns", tableName.Split('.'));
        foreach (DataRow row in columns.Rows)
        {
            yield return new DbColumnInfo()
            {
                Name = row.Field<string>(3),
                OrdinalPosition = row.Field<short>(4),
                DataType = this.FormatDataType(row),
                IsNullable = string.Equals(row.Field<string>(6), "yes", StringComparison.InvariantCultureIgnoreCase),
                IsPrimaryKey = // ... ?
            };
        }
    }
}
public IEnumerable GetColumns(字符串提供程序名、字符串连接字符串、字符串表名)
{
DbProviderFactory=dbProviderFactorys.GetFactory(providerName);
使用(DbConnection=factory.CreateConnection())
使用(DbCommand=factory.CreateCommand())
{
connection.ConnectionString=ConnectionString;
connection.Open();
command.Connection=连接;
var columns=connection.GetSchema(“columns”,tableName.Split('.');
foreach(columns.Rows中的数据行)
{
返回新的DbColumnInfo()的产量
{
名称=行。字段(3),
序号位置=行字段(4),
DataType=此.FormatDataType(行),
IsNullable=string.Equals(行.字段(6),“是”,StringComparison.InvariantCultureIgnoreCase),
IsPrimaryKey=/?
};
}
}
}

恐怕您无法使用connection.GetSchema()确定

但作为一种解决方法,如果dataadapter适合您,您可以尝试:

    var da = factory.CreateDataAdapter();
    command.CommandText = "select * from Employees";
    da.SelectCommand = command;
    da.MissingSchemaAction = MissingSchemaAction.AddWithKey;

    var dtab = new DataTable();
    da.FillSchema(dtab, SchemaType.Source);

    foreach (DataColumn col in dtab.Columns)
    {
        string name = col.ColumnName;
        bool isNull = col.AllowDBNull;
        bool isPrimary = dtab.PrimaryKey.Contains(col);
    }

这适用于SQLITE和其他数据库:-

            string[] restrictions = new string[] { null, null,   strTable };
            DataTable tableInfo = Connection.GetSchema("IndexColumns", restrictions);

            if (tableInfo == null)
                throw new Exception("TableInfo null Error");

            foreach (DataRow test in tableInfo.Rows)
            {
                Console.WriteLine(test["column_name"]);             
            }
自从qes提出问题以来,我目前使用的(在Laszlo提供了他的工作解决方案之后,经过几个版本重构代码)并不像我希望的那样优雅,但它更高效,满足了我的需求。基本上,我提供了一个
DbInfoProvider
类,该类旨在为给定的提供者生成
DbTableInfo
DbColumnInfo
SqlDbInfoProvider
仅用于获取SQL Server的列信息:

public IEnumerable<DbColumnInfo> GetColumns(string connectionString, DbTableInfo table)
{
    DbProviderFactory factory = DbProviderFactories.GetFactory(this.providerName);
    using (DbConnection connection = factory.CreateConnection())
    using (DbCommand command = factory.CreateCommand())
    {
        connection.ConnectionString = connectionString;
        connection.Open();
        command.Connection = connection;
        command.CommandText = ColumnInfoQuery;
        command.CommandType = CommandType.Text;
        var tableSchema = factory.CreateParameter();
        tableSchema.ParameterName = "@tableSchema";
        tableSchema.DbType = DbType.String;
        tableSchema.Value = table.Schema;
        command.Parameters.Add(tableSchema);
        var tableName = factory.CreateParameter();
        tableName.ParameterName = "@tableName";
        tableName.DbType = DbType.String;
        tableName.Value = table.Name;
        command.Parameters.Add(tableName);

        var dataTable = new DataTable();
        using (var reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                yield return new DbColumnInfo()
                {
                    Name = reader.GetString(0),
                    OrdinalPosition = reader.GetInt32(1),
                    DataType = reader.GetString(2),
                    IsNullable = reader.GetBoolean(3),
                    IsPrimaryKey = reader.GetBoolean(4),
                    IsForeignKey = reader.GetBoolean(5),
                    IsUnique = reader.GetBoolean(6),
                };
            }
        }
    }
}
对, 您可以通过请求索引的模式来确定哪些列是主键。然后在索引中搜索特定列/表

DataTable indexes = conn.GetSchema("Indexes");
List<string> PrimaryKeys = new List<string>();
foreach (DataRow row in indexes.Rows)
  if (Convert.ToBoolean(row["PRIMARY_KEY"]))
    PrimaryKeys.Add(row["TABLE_NAME"] + "." + row["COLUMN_NAME"]);
DataTable index=conn.GetSchema(“索引”);
List PrimaryKeys=新列表();
foreach(index.Rows中的数据行)
if(Convert.ToBoolean(行[“主关键字]))
添加(行[“表名称”]+“+行[“列名称”]);

PrimaryKeys将包含数据库中的主键列表。只需检查您的[table].[column]是否在此列表中。

至少在Oracle ODP.Net提供程序中,GetSchema()有一个“PrimaryKeys”选项。我建议您使用不带参数的GetSchema()来查看为您的实现定义了哪些其他调用。此代码检索GetSchema()元定义,该元定义描述了Oracle提供程序的其他已实现GetSchema()调用

    private void GetSchemaMetaInfo(DbConnection connection)
    {
        var metaDataCollections = connection.GetSchema("MetaDataCollections");
        var dataSourceInformation = connection.GetSchema("DataSourceInformation");
        var dataTypes = connection.GetSchema("DataTypes");
        var restrictions = connection.GetSchema("Restrictions");
        var reservedWords = connection.GetSchema("ReservedWords");
    }

可以使用PrimaryKeys集合来确定主键 然后检索相应的索引名,然后从IndexColumns集合中获取构成索引和主键的列

String pkIndxNm = null;
List<String> lstPkColNms = new List<String>();

DataTable dt = dbConn.GetSchema("PrimaryKeys", new[] { owner, tblNm });
if (dt.Rows.Count == 1) {
    DataRow pkRow = dt.Rows[0];
    pkIndxNm = pkRow["INDEX_NAME"] as String;

    // Now use the IndexColumns collection to pick up the names of the 
    // columns which constitute the primary key.
    //
    dt = dbConn.GetSchema("IndexColumns", new[] { owner, pkIndxNm });
    foreach (DataRow icRow in dt.Rows) {
        String colNm = icRow["COLUMN_NAME"] as String;
        lstPkColNms.Add(colNm);
    }
}
这是我得到的,从中我知道在 数组的第一和第二个位置,以将其约束到适当的索引

用户|用户名|名称|用户名| 1

表|所有者|所有者|所有者| 1

表|表|表名|表名| 2

列|所有者|所有者|所有者| 1

列|表|表名|表名| 2

栏|栏|栏名|栏名| 3

视图|所有者|所有者|所有者| 1

视图|视图|视图名称|视图|名称| 2

同义词|所有者|所有者|所有者| 1

同义词|同义词|同义名|同义名| 2

序列|所有者|所有者|序列|所有者| 1

序列|序列|序列|序列|名称| 2

程序参数|所有者|所有者|所有者| 1

过程参数|对象名称|对象名称|对象名称| 2

功能|所有者|所有者|所有者| 1

函数|名称|名称|对象|名称| 2

索引列|所有者|所有者|索引|所有者| 1

索引列|名称|名称|索引|名称| 2

索引列|表格所有者|表格所有者|表格所有者| 3

索引列|表名|表名|表名| 4

索引列|列|列名|列名| 5

索引|所有者|所有者|所有者| 1

索引|名称|名称|索引|名称| 2

索引|表格所有者|表格所有者|表格所有者| 3

索引|表名|表名|表名| 4

包|所有者|所有者|所有者| 1

软件包|名称|软件包名称|对象|名称| 2

包装体|所有者|所有者|所有者| 1

包装体|名称|名称|对象|名称| 2

论点|所有者|所有者|所有者| 1

参数| PackageName | PackageName | PACKAGE|u NAME | 2

参数| ObjectName | ObjectName | OBJECT|u NAME | 3

参数| ArgumentName | ArgumentName |参数|名称| 4

程序|所有者|所有者|所有者| 1

程序|名称|名称|对象|名称| 2

唯一钥匙|所有者|所有者|所有者| 1

唯一键|表名|表名|表名| 2

唯一键|约束|名称|约束|名称| 3

主钥匙|所有者|所有者|所有者| 1

主键|表名|表名|表名| 2

PrimaryKeys |约束|名称|约束|名称| 3

外籍钥匙|外籍钥匙|所有人| FKCON.Owner | 1

外键|外键|表名|表名| FKCON.Table | 2

外键|外键|约束|名称|约束| FKCON.Constraint |名称| 3

ForeignKeyColumns | Owner | Owner | FKCOLS.Owner | 1

ForeignKeyColumns |表名|表名| FKCOLS.Table |表名| 2


ForeignKeyColumns | Constraint | Name | CONSTRAINTNAME | FKCOLS.Constraint | Name | 3

我考虑过这一点,但我还需要可靠地检索列的底层SQL数据类型(例如,
NVARCHAR(255)
对应于
System.String
)。就我所知
  DataTable dt = dbConn.GetSchema("Restrictions");
  AppLog.Log.Info("CollectionName | RestrictionName | ParameterName | " +
                  "RestrictionDefault | RestrictionNumber");
  AppLog.Log.Info(" ");
  foreach (DataRow r in dt.Rows) {
      String s = r["CollectionName"] as String;
      s += " | " + r["RestrictionName"] as String;
      s += " | " + r["ParameterName"] as String;
      s += " | " + r["RestrictionDefault"] as String;
      s += " | " + r["RestrictionNumber"].ToString();
      AppLog.Log.Info(s);
  }