Npgsql 的 IsNullable 总是 trune 而 IsAutoincrement 总是 false 吗?
Is IsNullable always trune and IsAutoincrement always false for Npgsql?
我有一个使用 VS2012 用 C# 编写的程序,它自动为数据库 tables 构建包装器 classes。我正在尝试更新它以确保智能处理空值(对我公司来说是一个新概念)。我们的大部分工作都是使用 PostgreSQL 完成的,我们通常使用 ODBC。我希望我的程序能够识别可空列和自动增量列。 DataColumn class 包括 IsNullable 和 IsAutoincrement 属性。我用每种类型的列样本创建了一些 table。使用 ODBC,发现所有列都可以为 null,并且不会自动递增。我认为那是因为 ODBC 没有实现所有功能,所以我用最新版本的 Npgsql 进行了尝试。我很惊讶地看到 Npgsql 还报告了所有可为 null 而不是自动递增的内容。我需要做些什么来设置这些属性吗?
这是我的 table 定义:
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();
}
}
}
我不太了解数据table,但我的猜测是因为源是查询的结果,所以查询本身不会显示源中的列是否可为空.例如,如果您插入了联接、文字或合并视图,则确定每一列的实际来源将变得越来越困难。我不认为结果集本身知道或关心列是否可为空。
据我所知,PostgreSQL 版本 10 之前的实例没有本机标识类型。在我看来,他们完成了同样的事情,但他们将各个部分缝合在一起,就像我们过去所做的那样。因此,我不知道您是否可以确定有关专栏的内容。也就是说,如果你做出合理的假设,你可能会接近。
为了满足您的两个需求,我将继续使用 informatio_schema.columns
table。像这样的东西肯定会解决可空方面,它会让你 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# 方法看起来有点粗糙,但希望它足以让你到达那里。
您必须了解在结果集上获取元数据信息(您似乎在做什么)与在 table 列上获取信息之间的区别 - 两者并不相同。
当您获取 table 的元数据时(通过 NpgsqlConnection.GetSchemaTable()
,Npgsql 会去查找所有它能找到的信息,包括空能力和 auto-increment。但是,当获取有关的信息时结果集,Npgsql 几乎没有 PostgreSQL 提供的信息,也不知道它是可空的还是自动增量的。
所以要获取所有信息,请使用 NpgsqlConnection.GetSchemaTable()
。
我有一个使用 VS2012 用 C# 编写的程序,它自动为数据库 tables 构建包装器 classes。我正在尝试更新它以确保智能处理空值(对我公司来说是一个新概念)。我们的大部分工作都是使用 PostgreSQL 完成的,我们通常使用 ODBC。我希望我的程序能够识别可空列和自动增量列。 DataColumn class 包括 IsNullable 和 IsAutoincrement 属性。我用每种类型的列样本创建了一些 table。使用 ODBC,发现所有列都可以为 null,并且不会自动递增。我认为那是因为 ODBC 没有实现所有功能,所以我用最新版本的 Npgsql 进行了尝试。我很惊讶地看到 Npgsql 还报告了所有可为 null 而不是自动递增的内容。我需要做些什么来设置这些属性吗?
这是我的 table 定义:
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();
}
}
}
我不太了解数据table,但我的猜测是因为源是查询的结果,所以查询本身不会显示源中的列是否可为空.例如,如果您插入了联接、文字或合并视图,则确定每一列的实际来源将变得越来越困难。我不认为结果集本身知道或关心列是否可为空。
据我所知,PostgreSQL 版本 10 之前的实例没有本机标识类型。在我看来,他们完成了同样的事情,但他们将各个部分缝合在一起,就像我们过去所做的那样。因此,我不知道您是否可以确定有关专栏的内容。也就是说,如果你做出合理的假设,你可能会接近。
为了满足您的两个需求,我将继续使用 informatio_schema.columns
table。像这样的东西肯定会解决可空方面,它会让你 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# 方法看起来有点粗糙,但希望它足以让你到达那里。
您必须了解在结果集上获取元数据信息(您似乎在做什么)与在 table 列上获取信息之间的区别 - 两者并不相同。
当您获取 table 的元数据时(通过 NpgsqlConnection.GetSchemaTable()
,Npgsql 会去查找所有它能找到的信息,包括空能力和 auto-increment。但是,当获取有关的信息时结果集,Npgsql 几乎没有 PostgreSQL 提供的信息,也不知道它是可空的还是自动增量的。
所以要获取所有信息,请使用 NpgsqlConnection.GetSchemaTable()
。