Npgsql DataReader 使用 DateTime 类型表示没有时区的时间而不是 TimeSpan
Npgsql DataReader uses DateTime type for time without time zone rather than TimeSpan
我正在 select 使用 Npgsql 在 Postgres 中使用 table。此 table 有一个类型为 time without time zone
的列 auction_time
。 reader returns 将此列 auction_time
转换为 DateTime
而不是我期望的 TimeSpan
的数据 table。当将数据批量复制到 time(7)
类型的 MS SQLServer 中的另一个 table 时,这会导致出现问题。
这是我 select 输出的地方:
using (NpgsqlConnection connection = new NpgsqlConnection(String.Format(PropertyDataDB.ConnectionStringWithSearchPath, schemaName)))
{
connection.Open();
NpgsqlCommand command = new NpgsqlCommand
{
CommandText = commandText,
Connection = connection
};
using (NpgsqlDataReader dataReader = command.ExecuteReader())
{
DataTable dt = new DataTable();
//dt = dataReader.GetSchemaTable();
dt.Load(dataReader);
BulkCopy(destinationTable, dt);
}
}
所以 dt 中的 auction_type
将是 DateTime
类型,并且所有时间的前面都会附加日期 1/1/0001
。我该如何防止这种情况?
谢谢。
这就是我最后做的,如果你需要保持在版本上,只做这样的事情 2.x。它有效,但我一点也不喜欢它。我只是克隆数据 table,更改数据类型,并在需要时执行 "cast"。
using (NpgsqlConnection connection = new NpgsqlConnection(String.Format(PropertyDataDB.ConnectionStringWithSearchPath, schemaName)))
{
connection.Open();
NpgsqlCommand command = new NpgsqlCommand
{
CommandText = commandText,
Connection = connection
};
using (NpgsqlDataReader dataReader = command.ExecuteReader())
{
DataTable dt = new DataTable();
dt.Load(dataReader);
if (dt.Columns.Contains("auction_time"))
{
DataTable clone = dt.Clone();
clone.Columns["auction_time"].DataType = typeof(TimeSpan);
foreach (DataRow row in dt.Rows)
{
DataRow newRow = clone.NewRow();
foreach (DataColumn column in dt.Columns)
{
if (column.ColumnName == "auction_time" && !row.IsNull(column.Ordinal))
{
newRow[column.Ordinal] = ((DateTime)row[column.Ordinal]).TimeOfDay;
}
else
{
newRow[column.Ordinal] = row[column.Ordinal];
}
}
}
dt = clone;
}
BulkCopy(destinationTable, dt);
}
}
另一个修复是将 Npgsql 升级到版本 3.x,此问题已修复。 http://www.npgsql.org/doc/release-notes/3.0.html
我的解决方案:
class Model
{
public readonly static string tableName = "tb_name";
public Int32 id {get; private set;}
public string auth_token {get; private set;}
public TimeSpan column_time {get; set;} // this is the target !!
/* more columns for model object here.. */
public static NpgsqlCommand Query(string sql = null )
{
// treturn new NpgsqlCommand from my global NpgsqlConnection definition
return Connection.CreateObject().Query(sql);
}
public static Model FindByPk(int id)
{
NpgsqlCommand query = Query(string.Format("select * from {0} where id = @id order by id asc limit 1" , tableName ));
query.Parameters.AddWithValue("@id", id);
NpgsqlDataReader reader = query.ExecuteReader();
if(reader.HasRows == false)
return null;
Model obj = new Model();
return (obj.SetDbProperties(reader)) ? obj : null;
}
protected bool SetDbProperties(NpgsqlDataReader reader)
{
if(reader.IsClosed)
return false;
try{
reader.Read();
for (int i = 0; i < reader.FieldCount; i++)
{
string key = reader.GetName(i);
if(reader.GetValue(i) == DBNull.Value )
continue;
//@todo add dinamic setter by key value
// https://titiandragomir.wordpress.com/2009/12/22/getting-and-setting-property-values-dynamically/
switch(key)
{
case "id":
this.id = reader.GetInt32(i);
break;
case "auth_token":
this.auth_token = reader.GetString(i);
break;
case "column_time":
// solution!!!!
var colValue = reader.GetTime(i);
this.horario_dia1_init = new TimeSpan(0, colValue.Hours , colValue.Minutes, colValue.Seconds, colValue.Microseconds );
break;
}
}
reader.Close();
return true;
}
catch(Exception e){
Console.WriteLine(e.Message);
return false;
}
}
}
使用示例:
public static void Main(string[] args)
{
Model model = Model.FindByPk(1);
if(model == null)
Console.WriteLine("record not found");
else {
Console.WriteLine("model.id {0}", model.id);
Console.WriteLine("model.auth_token {0}", model.auth_token);
Console.WriteLine("model.column_time {0}", model.column_time);
}
Console.Read();
}
我正在 select 使用 Npgsql 在 Postgres 中使用 table。此 table 有一个类型为 time without time zone
的列 auction_time
。 reader returns 将此列 auction_time
转换为 DateTime
而不是我期望的 TimeSpan
的数据 table。当将数据批量复制到 time(7)
类型的 MS SQLServer 中的另一个 table 时,这会导致出现问题。
这是我 select 输出的地方:
using (NpgsqlConnection connection = new NpgsqlConnection(String.Format(PropertyDataDB.ConnectionStringWithSearchPath, schemaName)))
{
connection.Open();
NpgsqlCommand command = new NpgsqlCommand
{
CommandText = commandText,
Connection = connection
};
using (NpgsqlDataReader dataReader = command.ExecuteReader())
{
DataTable dt = new DataTable();
//dt = dataReader.GetSchemaTable();
dt.Load(dataReader);
BulkCopy(destinationTable, dt);
}
}
所以 dt 中的 auction_type
将是 DateTime
类型,并且所有时间的前面都会附加日期 1/1/0001
。我该如何防止这种情况?
谢谢。
这就是我最后做的,如果你需要保持在版本上,只做这样的事情 2.x。它有效,但我一点也不喜欢它。我只是克隆数据 table,更改数据类型,并在需要时执行 "cast"。
using (NpgsqlConnection connection = new NpgsqlConnection(String.Format(PropertyDataDB.ConnectionStringWithSearchPath, schemaName)))
{
connection.Open();
NpgsqlCommand command = new NpgsqlCommand
{
CommandText = commandText,
Connection = connection
};
using (NpgsqlDataReader dataReader = command.ExecuteReader())
{
DataTable dt = new DataTable();
dt.Load(dataReader);
if (dt.Columns.Contains("auction_time"))
{
DataTable clone = dt.Clone();
clone.Columns["auction_time"].DataType = typeof(TimeSpan);
foreach (DataRow row in dt.Rows)
{
DataRow newRow = clone.NewRow();
foreach (DataColumn column in dt.Columns)
{
if (column.ColumnName == "auction_time" && !row.IsNull(column.Ordinal))
{
newRow[column.Ordinal] = ((DateTime)row[column.Ordinal]).TimeOfDay;
}
else
{
newRow[column.Ordinal] = row[column.Ordinal];
}
}
}
dt = clone;
}
BulkCopy(destinationTable, dt);
}
}
另一个修复是将 Npgsql 升级到版本 3.x,此问题已修复。 http://www.npgsql.org/doc/release-notes/3.0.html
我的解决方案:
class Model
{
public readonly static string tableName = "tb_name";
public Int32 id {get; private set;}
public string auth_token {get; private set;}
public TimeSpan column_time {get; set;} // this is the target !!
/* more columns for model object here.. */
public static NpgsqlCommand Query(string sql = null )
{
// treturn new NpgsqlCommand from my global NpgsqlConnection definition
return Connection.CreateObject().Query(sql);
}
public static Model FindByPk(int id)
{
NpgsqlCommand query = Query(string.Format("select * from {0} where id = @id order by id asc limit 1" , tableName ));
query.Parameters.AddWithValue("@id", id);
NpgsqlDataReader reader = query.ExecuteReader();
if(reader.HasRows == false)
return null;
Model obj = new Model();
return (obj.SetDbProperties(reader)) ? obj : null;
}
protected bool SetDbProperties(NpgsqlDataReader reader)
{
if(reader.IsClosed)
return false;
try{
reader.Read();
for (int i = 0; i < reader.FieldCount; i++)
{
string key = reader.GetName(i);
if(reader.GetValue(i) == DBNull.Value )
continue;
//@todo add dinamic setter by key value
// https://titiandragomir.wordpress.com/2009/12/22/getting-and-setting-property-values-dynamically/
switch(key)
{
case "id":
this.id = reader.GetInt32(i);
break;
case "auth_token":
this.auth_token = reader.GetString(i);
break;
case "column_time":
// solution!!!!
var colValue = reader.GetTime(i);
this.horario_dia1_init = new TimeSpan(0, colValue.Hours , colValue.Minutes, colValue.Seconds, colValue.Microseconds );
break;
}
}
reader.Close();
return true;
}
catch(Exception e){
Console.WriteLine(e.Message);
return false;
}
}
}
使用示例:
public static void Main(string[] args)
{
Model model = Model.FindByPk(1);
if(model == null)
Console.WriteLine("record not found");
else {
Console.WriteLine("model.id {0}", model.id);
Console.WriteLine("model.auth_token {0}", model.auth_token);
Console.WriteLine("model.column_time {0}", model.column_time);
}
Console.Read();
}