我有一个使用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();
}
}
}
答案 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#方法在边缘看起来很粗糙,但希望它足以让你到达那里。