We have recently updated our solution from Visual Studio 2010 to VS 2017 & .NET Framework 4.0 to 4.6.1.
There are no changes in database which is running on Postgres 9.4.
This also included upgrading Npgsql DLL from version 2 to version 3.
We have a piece of code like below:
using (MemoryStream memoryStream = new MemoryStream())
{
dataTable.WriteXml(memoryStream, XmlWriteMode.IgnoreSchema);
.
.
.
We have a PostgreSQL stored procedure which is returning columns of array data types (string[], bool[], int[] etc.).
In .NET 4.0, NpgSql 2 version above line was working fine with no issues. But with new setup, we are getting a serialization error.
Type 'System.String[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' does not implement IXmlSerializable interface therefore can not proceed with serialization. at System.Data.XmlDataTreeWriter.XmlDataRowWriter(DataRow row, String encodedTableName)
at System.Data.XmlDataTreeWriter.Save(XmlWriter xw, Boolean writeSchema)
at System.Data.DataTable.WriteXml(XmlWriter writer, XmlWriteMode mode, Boolean writeHierarchy)
at System.Data.DataTable.WriteXml(Stream stream, XmlWriteMode mode, Boolean writeHierarchy)
The main thing I could notice in VS debugger was that the DataType of those array columns are shown as "System.Array" from VS 2017 but before (in 2010) it was showing specific type array like "System.String[]".
Anyone knows what is going on here? Any help/suggestion is highly appreciated.
Here is a simple code that can be used to replicate the issue.
using System.Configuration;
using Npgsql;
using System.Data;
using System.IO;
namespace NpgSqlArrayTest
{
public class Program
{
public static void Main(string[] args)
{
string connectionString = ConfigurationManager.ConnectionStrings["TestConnection"].ConnectionString;
NpgsqlConnection npgsqlConnection = new NpgsqlConnection(connectionString);
DataTable resultTable = new DataTable();
NpgsqlDataAdapter npgsqlDataAdapter = new NpgsqlDataAdapter("select * from \"FunctionReturnsArray\"();", npgsqlConnection);
npgsqlConnection.Open();
npgsqlDataAdapter.Fill(resultTable);
resultTable.TableName = "FunctionReturnsArray";
npgsqlConnection.Close();
using (MemoryStream memoryStream = new MemoryStream())
{
resultTable.WriteXml(memoryStream, XmlWriteMode.IgnoreSchema);
}
}
}
}
This is the stored procedure.
CREATE OR REPLACE FUNCTION "FunctionReturnsArray"()
RETURNS integer[] AS
$BODY$
declare
v_Count integer;
v_Array integer[];
begin
v_Count = 0;
while v_Count < 10 loop
v_Array = array_append(v_Array, v_Count);
v_Count = v_Count + 1;
end loop;
return v_Array;
end;
$BODY$
LANGUAGE plpgsql STABLE
COST 100;