【问题标题】:Getting if a Column is nullable (declared as not null or implicit declared nullable) using SqlClient on C#使用 C# 上的 SqlClient 获取列是否可为空(声明为非空或隐式声明为空)
【发布时间】:2020-02-14 14:00:10
【问题描述】:

我有这段代码,它显示了我使用SqlClient 创建的数据库,但我不知道如何检查表中的列是否添加为可空或不可空。

string[] defaultTables = { "AspNetUsers", "AspNetRoleClaims", "AspNetUserClaims", "AspNetUserLogins", "AspNetUserRoles", "AspNetUserTokens", "AspNetRoles", "__EFMigrationsHistory" };
dblist.ForEach((string DbName) => {
    strConnection = $@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog={DbName};Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";

    using (SqlConnection conn = new SqlConnection(strConnection)) {
        conn.Open();
        using (cmdSql = new SqlCommand(strConnection, conn)) {
            DataTable dt = conn.GetSchema("Tables");

            foreach (DataRow row in dt.Rows) {
                string tablename = row[2].ToString();
                if (!defaultTables.Any(x => x == tablename)) {
                    tables.Add(tablename);

                    using (cmdSql = new SqlCommand($"Select * FROM {tablename}", conn)) {
                        SqlDataReader reader = cmdSql.ExecuteReader();
                        if (reader.Read()) {
                            for (int i = 0; i < reader.FieldCount; i++)
                                Console.Write(reader.GetName(i) + " " + reader.GetDataTypeName(i) + $"" + ',');
                        }
                    }
                }
            }
        }
    }
});

【问题讨论】:

  • 使用 INFORMATION_SCHEMA.Columns 系统视图,您的信息在 IS_NULLABLE 列中
  • 好吧,SqlDataReader 不会告诉你 - 它只是读取结果,它不关心列是 NULL 还是 NOT NULL
  • 或许这条 SQL 语句对你有帮助:stackoverflow.com/questions/5204684/…
  • @stuartd 我不知道,谢谢,因为它返回了值类型,如果它可以为空,它也可以返回。
  • 检查这里返回的类型是否可以为空:reader.GetDataTypeName(i) 使用 g check for nullable。我不确定 sqlite 是否有元数据,但如果有,我会使用它,因为它会回答更多问题。

标签: c# sql-server


【解决方案1】:

您提取此类信息的方法似乎有点复杂。我们在数据库中有 INFORMATION_SCHEMA 视图,其中包含所需的信息。

例如:

using(SqlConnection con = new SqlConnection(.....)) 
{
    con.Open();
    DataTable dt = new DataTable();

    // Get info on all tables...
    SqlCommand cmd = new SqlCommand(@"SELECT * FROM INFORMATION_SCHEMA.TABLES 
                                      WHERE TABLE_TYPE = 'BASE TABLE'", con);
    dt.Load(cmd.ExecuteReader());
    foreach (DataRow r in dt.Rows)
    {
        // Get info on the current table's columns
        string sqltext = $"SELECT * FROM INFORMATION_SCHEMA.Columns 
                           WHERE TABLE_NAME = '{r.Field<string>("TABLE_NAME")}'";
        SqlCommand cmd1 = new SqlCommand(sqltext, con);
        DataTable dt1 = new DataTable();
        dt1.Load(cmd1.ExecuteReader());
        foreach (DataRow x in dt1.Rows)
        {
            Console.WriteLine($"Table:{x.Field<string>("TABLE_NAME")}");
            Console.WriteLine($"Column:{x.Field<string>("COLUMN_NAME")}");
            Console.WriteLine($"Data type:{x.Field<string>("DATA_TYPE")}");
            Console.WriteLine($"Nullable:{x.Field<string>("IS_NULLABLE")}");
        }
    }

【讨论】:

  • 在我的帖子的 for 循环中这样使用它怎么样? ((DataRow)schemaTable.Rows[i]).Field&lt;bool&gt;("AllowDBNull")
【解决方案2】:

它不是 100% 可靠的,但是数据阅读器上的 GetSchemaTable() 可以显示这一点,如果它知道(并非总是如此);具体来说,您正在寻找 AllowDBNull 属性。不过,这并不是一个很好的 API - 它返回一个您需要调查的 DataTable,因此可能需要花点时间才能找到您想要的东西。

citation

【讨论】:

  • 是的,我发现它是这样工作的(写在 for 循环中)((DataRow)schemaTable.Rows[i]).Field&lt;bool&gt;("AllowDBNull")
  • @PontiacGTX 如果您认为这回答了您的问题,那么请尽自己的一份力量并将其标记为答案。并了解您接受这种方法的风险——也许在代码中添加注释以防万一以后有人来。
  • @Smor 好点 - 正如文档所说 “设置消费者是否可以将列设置为空值 或者如果提供者无法确定消费者是否可以将列设置为一个空值。否则,不设置。一个列可能包含空值,即使它不能设置为空值。”
  • @stuartdall 答案似乎是有效的。我之前尝试过使用 AllowDBNull 和不同的代码,并且可能给出了表元数据本身,并且与属于我查询的表的列的实际可空性不同。
猜你喜欢
  • 2017-11-21
  • 2015-05-08
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 2019-07-09
  • 2020-06-11
  • 1970-01-01
相关资源
最近更新 更多