对于Npgsql,IsNullable是否始终是真的并且IsAutoincrement始终为false?

时间:2018-04-04 15:01:08

标签: npgsql

我有一个使用VS2012用C#编写的程序,它自动为数据库表构建包装类。我正在尝试更新它以确保智能处理空值(我公司的新概念)。我们的大部分工作都是使用PostgreSQL完成的,我们通常使用ODBC。我希望我的程序能够识别可空和自动增量列。 DataColumn类包含IsNullable和IsAutoincrement属性。我创建了一个包含每种类型列的样本的小表。使用ODBC,发现所有列都可以为空,而不是自动增量。我认为这是因为ODBC没有实现所有内容,所以我尝试使用最新版本的Npgsql。我很惊讶地看到Npgsql也报告了所有可空的而不是自动增量。我需要做些什么来设置这些属性吗?

这是我的表定义:

CREATE TABLE nullable_test
(
  key_field bigserial NOT NULL,
  non_nullable_integer integer NOT NULL,
  nullable_integer integer
)
WITH (
  OIDS=FALSE
);

这是我的测试程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.Odbc;

using Npgsql;

namespace NullableTest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                NpgsqlConnection npgConn = new NpgsqlConnection();
                NpgsqlConnectionStringBuilder connStringBuilder = new NpgsqlConnectionStringBuilder();
                connStringBuilder.Host = "localhost";
                connStringBuilder.Database = "Stripco";
                connStringBuilder.Username = "caps";
                connStringBuilder.Password = "asdlkjqp";
                npgConn.ConnectionString = connStringBuilder.ToString();
                npgConn.Open();
                Console.WriteLine("Database open using Npgsql");

                DataSet npgsqlDataSet = new DataSet();
                NpgsqlDataAdapter npgsqlAdapter = new NpgsqlDataAdapter("select * from nullable_test", npgConn);
                npgsqlAdapter.Fill(npgsqlDataSet);
                Console.WriteLine("Data set is filled.");

                DataTable table = npgsqlDataSet.Tables[0];
                DataColumn keyColumn = npgsqlDataSet.Tables[0].Columns["key_field"];
                DataColumn nonNullableColumn = npgsqlDataSet.Tables[0].Columns["non_nullable_integer"];
                DataColumn nullableColumn = npgsqlDataSet.Tables[0].Columns["nullable_integer"];

                Console.WriteLine("Key column is " + (keyColumn.AutoIncrement ? "" : " not ") + " autoincrementing");
                Console.WriteLine("Key column is " + (keyColumn.AllowDBNull ? "" : " not ") + " allowing nulls.");
                Console.WriteLine("Non-nullable column is " + (nonNullableColumn.AutoIncrement ? "" : " not ") + " autoincrementing");
                Console.WriteLine("Non-nullable column is " + (nonNullableColumn.AllowDBNull ? "" : " not ") + " allowing nulls.");
                Console.WriteLine("Nullable column is " + (nullableColumn.AutoIncrement ? "" : " not ") + " autoincrementing");
                Console.WriteLine("Nullable column is " + (nullableColumn.AllowDBNull ? "" : " not ") + " allowing nulls.");

                npgConn.Close();

            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to open database: " + ex.Message);
            }
            Console.WriteLine("Press any key");
            Console.ReadKey();
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您必须了解获取结果集上的元数据信息(您似乎在做什么)与获取表列上的信息之间的区别 - 两者不相同。

当您获取表的元数据时(通过NpgsqlConnection.GetSchemaTable(),Npgsql会查找它可以获得的所有信息,包括null能力和自动增量。但是,当获取有关结果集的信息时,Npgsql几乎没有信息由PostgreSQL提供,无法知道它是否可以为空或自动增量。

因此,要获取所有信息,请使用NpgsqlConnection.GetSchemaTable()

答案 1 :(得分:1)

我不太了解数据表,但我的猜测是因为源是查询的结果,查询本身不会显示源中的列是否可以为空。例如,如果您已插入连接,文字或合并视图,则确定每列实际来自哪里将变得越来越困难。我不认为结果集本身知道或关心列是否可以为空。

根据我的理解,PostgreSQL的早期版本10实例没有本机身份类型。在我看来,他们完成了同样的事情,但是他们按照我们当天所做的方式将各个部分缝合在一起。因此,我不知道你肯定可以确定一个专栏。也就是说,如果你做出合理的假设,你可能会接近。

对于您的两个需求,我只需继续使用informatio_schema.columns表。像这样的东西肯定会解决可以为空的方面,它会让你获得90%的身份:

select
  is_nullable = 'YES',
  column_default like 'nextval%'
from information_schema.columns
where
  table_schema = :SCHEMA and
  table_name = :TABLE_NAME and
  column_name = :COLUMN

C#实现看起来像这样:

private bool IsSerial(string Schema, string Table, string Column)
{
    bool result = false;

    NpgsqlCommand cmd = new NpgsqlCommand(Resources.Sql, Connection);
    cmd.Parameters.AddWithValue("SCHEMA", Schema);
    cmd.Parameters.AddWithValue("TABLE_NAME", Table);
    cmd.Parameters.AddWithValue("COLUMN", Column);

    NpgsqlDataReader reader = cmd.ExecuteReader();

    if (reader.HasRows)
    {
        reader.Read();
        result = reader.GetBoolean(1);
    }

    reader.Close();

    return result;
}

您可以将GetBoolean(1)更改为GetBoolean(0)以获取可以为空的作品。

我的C#方法在边缘看起来很粗糙,但希望它足以让你到达那里。