我正在实现客户端软件和数据库之间的抽象层。该软件最初是使用OleDb编写的,并且运行良好。我们已经通过Data组件处理了数据访问,但客户端软件仍然使用基于OleDb的过程调用其过程。准确地说,我们仍然会将System.Data.OleDb.OleDbParameter[]数组传递到Data组件,它会将System.Data.DataSet对象返回给客户端。
我们现在正在编写一个API,作为数据库和数据组件之间的中间层,因此为了尽可能少地影响客户端软件,我们仍然会以完全相同的方式调用其方法。在内部,数据组件将序列化我们传递到JSON中的OleDbParameter[]数组并调用API,这反过来又将返回序列化为JSON的数据集,以便我们的数据组件可以将它们反序列化为System.Data.DataSet,客户端软件不会知道。
这就是我们遇到的一个奇怪的障碍。
在尝试了System.Text.Json和System.Web.Script.Serialization之后,我发现这两种方法都不能很好地与DataSet一起工作。在尝试序列化System.Data.DataSet对象时,这两个对象似乎都存在循环引用问题。在这里,NewtonSoft.json来拯救:
使用NewtonSoft.json序列化DataSet很容易:
string sData = string.Empty;
Newtonsoft.Json.JsonSerializerSettings oSet = new Newtonsoft.Json.JsonSerializerSettings();
sData = Newtonsoft.Json.JsonConvert.SerializeObject(value: oDS, type: oDS.GetType(), settings: oSet);
将其反序列化回DataSet也是如此
System.Data.DataSet oDS = null;
oDS = Newtonsoft.Json.JsonConvert.DeserializeObject<System.Data.DataSet>(value: sData);
所以你会觉得这个选择很容易。NewtonSoft.Json是的,没错。除了...这让我对参数有问题
string sParameters = string.Empty;
System.Data.OleDb.OleDbParameter oXML;
oXML = new System.Data.OleDb.OleDbParameter(name: "XML", dataType: System.Data.OleDb.OleDbType.VarWChar, size: -1);
oXML.Value = "NotRelevantToThisQuestion";
System.Data.OleDb.OleDbParameter oTotalRecords;
oTotalRecords = new System.Data.OleDb.OleDbParameter(name: "TotalRecords", dataType: System.Data.OleDb.OleDbType.Integer);
oTotalRecords.Value = 0;
oTotalRecords.Direction = System.Data.ParameterDirection.InputOutput;
System.Data.OleDb.OleDbParameter[] oParms;
oParms = new System.Data.OleDb.OleDbParameter[] {oXML, oTotalRecords };
Newtonsoft.Json.JsonSerializerSettings oSet = new Newtonsoft.Json.JsonSerializerSettings();
sParameters = Newtonsoft.Json.JsonConvert.SerializeObject(value: oParms, type: oParms.GetType(), settings: oSet);
它似乎生成了一个JSON字符串,列出了这两个参数,但它们的属性都不存在。得到的JSON是:
["XML","TotalRecords"]
我可以使用System.Web.Serialization.JavaScriptSerializer让那个程序正常工作
System.Web.Script.Serialization.JavaScriptSerializer oSer;
oSer = new System.Web.Script.Serialization.JavaScriptSerializer();
sParameters = oSer.Serialize(oParms);
这产生:
[{"DbType":16,"OleDbType":202,"ParameterName":"XML","Precision":0,"Scale":0,"Value":"NotRelevantToThisQuestion","Direction":1,"IsNullable":false,"Size":-1,"SourceColumn":"","SourceColumnNullMapping":false,"SourceVersion":512},{"DbType":11,"OleDbType":3,"ParameterName":"TotalRecords","Precision":0,"Scale":0,"Value":0,"Direction":3,"IsNullable":false,"Size":0,"SourceColumn":"","SourceColumnNullMapping":false,"SourceVersion":512}]
在调用之后,Input/Output参数获得一个值,然后我还可以在接收端对该值进行序列化、发送回和反序列化,以允许我读取它的值,以及我已经使用NewtonSoft.json反序列化的DataSet
System.Data.OleDb.OleDbParameter[] oParms;
System.Web.Script.Serialization.JavaScriptSerializer oSer;
oSer = new System.Web.Script.Serialization.JavaScriptSerializer();
oParms = oSer.Deserialize<System.Data.OleDb.OleDbParameter[]>(sParameters);
所以如果你有足够的耐心,读到这里,我可以想象你现在在想什么:“只需使用NewtonSoft.Json作为您的DataSet,使用System.Web.Script.Serialization.JavaScriptSerializer作为您的参数即可。你有什么问题?”
当然可以。但是我不得不用两个不同的包来做一个包应该能处理的工作。说到这里,我终于可以回答我的问题了:
**是否有任何方法可以用一个包同时处理序列化/反序列化需求?只要它被清楚地记录下来,我很乐意使用我已经提到的3个软件包中的任何一个,甚至你可能在这里展示的另一个软件包。
1条答案
按热度按时间0lvr5msh1#
有两个问题我必须解决。第一个问题是如何序列化单个OleDbParameter。对于那个问题,已经有了@dbc指出的解决方案:
Newtonsoft.JSON无法转换具有TypeConverter属性的模型
对于OleDbParameter,我添加了以下内容:
我添加了NoTypeConverterJsonConverter类
这允许我序列化单个System.Data.OleDb.OleDbParameter,但我需要序列化它们的数组,我通过定义一个NoTypeConverterJsonConverter<System.Data.OleDb.OleDbParameter[]>来尝试
但是当我尝试使用它时,它导致了一个ArgumentException。
我最终发现可以通过将Array移动到System.Collections.Generic.List来避免这种情况<System.Data.OleDb.OleDbParameter>
这个,我能够序列化没有问题
反序列化也很容易:
非常感谢@dbc的帮助。