jyao jyao - 1 month ago 18
C# Question

How to deal with DBNull in DataContractSerializer?

I have the following C# code

using System.Runtime.Serialization;
using System.IO;
using System.Data;
// create a datatable with two columns [c1] and [c2]
var dt = new System.Data.DataTable("MyTable");

dt.Columns.Add(new DataColumn("c1", typeof(System.Int32)));
dt.Columns.Add(new DataColumn("c2", typeof(System.String)));



//create a new and populate it
var dr = dt.NewRow();
dr["c1"] = 1;
//dr["c2"]="hello"; //purposely commented out, if not, there is NO error

dt.Rows.Add(dr);

var s = new System.Runtime.Serialization.DataContractSerializer(typeof(object[]));
var mem = new MemoryStream();

// the following line will report error
s.WriteObject(mem, dt.Rows[0].ItemArray);
// other lines ... which have nothing to do with this question


If I do not populate column [c2], it means there is DBNull value in this data row, then I will encounter error when trying to run s.WriteObject().

Error:


Type 'System.DBNull' with data contract name
'DBNull:http://schemas.datacontract.org/2004/07/System' is not
expected. Consider using a DataContractResolver if you are using
DataContractSerializer or add any types not known statically to the
list of known types - for example, by using the KnownTypeAttribute
attribute or by adding them to the list of known types passed to the
serializer.


But according to MS document "Types Supported by the Data Contract Serializer"


The DBNull type is treated in a special way. It is a singleton type,
and upon deserialization the deserializer respects the singleton
constraint and points all DBNull references to the singleton instance.
Because DBNull is a serializable type, it demands
SerializationFormatter permission.


DBNull seems to be a supported type, and I am really confused here.
Could any guru share a few lights please? such as what should I do?

I know I can scan all table rows and find if a column value equals DBNull.Value, if so, I set an empty string or something for this column, but this is not what I want because this will "tamper" the DataTable values.

Thanks in advance for your help !

Answer

Add DBNull to the knownTypes list

var s = new DataContractSerializer(typeof(object[]), new [] { typeof(DBNull) });
Comments