为了优化WebService传输大数据量DataSet的性能,搜索各大网站资料,尤其是参考了台湾msdn网站的一篇文章,得到一个方案,但是遇到如下问题:
WebService端代码:
[WebMethod]
public Byte[] GetDsBytes()
{
DataSet ds = new DataSet();
//这里循环将20列,10000行记录表加入到DataSet中 DataSetSurrogate sds = new DataSetSurrogate(ds); //DataSetSurrogate这个是微软官方提供的一个压缩DataSet的类库
MemoryStream s = new MemoryStream();
s.Position = 0;
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(s,sds); byte[] e = s.ToArray();
//这里测试过,直接反序列化成DataSet是成功的。 s.Close(); return e; //返回二进制序列化过的DataSet byte[]
}
客户端Winform代码:
private xxxx ws = xxxx...//实例化WebService
private void button2_Click(object sender, System.EventArgs e)
{
Byte [] bb = this.ws.GetDsBytes(); MemoryStream br = new MemoryStream(bb);
br.Position = 0;
BinaryFormatter bf = new BinaryFormatter();
object o = bf.Deserialize(br);//这里反序列化出错,错误信息如下,其中WebService1是WebService的命名空间
//未处理的“System.Runtime.Serialization.SerializationException”类型的异常出现在 mscorlib.dll 中。
//其他信息: 无法找到程序集 WebService1, Version=1.0.2227.16697, Culture=neutral, PublicKeyToken=null。 DataSetSurrogate sds = (DataSetSurrogate)o;
DataSet ds = sds.ConvertToDataSet(); br.Close(); this.dataGrid1.DataSource = ds;
}查了很多资料,csdn也有很多人问这个问题,但是都没有答案,好像是将命名空间名和类名也都序列化到二进制数组中,反序列化的时候无法对应起来,而且我客户端重新建立了一个和WebService命名空间和类库名称相同的类来接收二进制数组,再反序列化也报同样的错。期待高人出现帮忙解答,谢了!!!!!!
WebService端代码:
[WebMethod]
public Byte[] GetDsBytes()
{
DataSet ds = new DataSet();
//这里循环将20列,10000行记录表加入到DataSet中 DataSetSurrogate sds = new DataSetSurrogate(ds); //DataSetSurrogate这个是微软官方提供的一个压缩DataSet的类库
MemoryStream s = new MemoryStream();
s.Position = 0;
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(s,sds); byte[] e = s.ToArray();
//这里测试过,直接反序列化成DataSet是成功的。 s.Close(); return e; //返回二进制序列化过的DataSet byte[]
}
客户端Winform代码:
private xxxx ws = xxxx...//实例化WebService
private void button2_Click(object sender, System.EventArgs e)
{
Byte [] bb = this.ws.GetDsBytes(); MemoryStream br = new MemoryStream(bb);
br.Position = 0;
BinaryFormatter bf = new BinaryFormatter();
object o = bf.Deserialize(br);//这里反序列化出错,错误信息如下,其中WebService1是WebService的命名空间
//未处理的“System.Runtime.Serialization.SerializationException”类型的异常出现在 mscorlib.dll 中。
//其他信息: 无法找到程序集 WebService1, Version=1.0.2227.16697, Culture=neutral, PublicKeyToken=null。 DataSetSurrogate sds = (DataSetSurrogate)o;
DataSet ds = sds.ConvertToDataSet(); br.Close(); this.dataGrid1.DataSource = ds;
}查了很多资料,csdn也有很多人问这个问题,但是都没有答案,好像是将命名空间名和类名也都序列化到二进制数组中,反序列化的时候无法对应起来,而且我客户端重新建立了一个和WebService命名空间和类库名称相同的类来接收二进制数组,再反序列化也报同样的错。期待高人出现帮忙解答,谢了!!!!!!
-->
object[] o = (object[])bf.Deserialize(br);
//然后
for (int i=0; i<o.Length; i++)
{
if (o[i]!=null && o[i] is DataSetSurrogate)
{
o[i] = ((DataSetSurrogate)o[i]).ConvertToDataSet();
}
}
如下我的代码,不知是否对你有用!
[WebMethod(Description="获取业务资料远程DATASET")]
public byte[] SurrogateRead1()
{
oracleconnxxj.Open();
xxjclxxds.SelectCommand.ExecuteNonQuery();
xxjclxxds.Fill(dataSet11,"VEHICLE");
sds = new DataSetSurrogate(dataSet11);
MemoryStream s= new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(s,sds);
byte[] e = s.ToArray();
oracleconnxxj.Close();
return e;
}客户端调用 byte [] bb=dsclxx.SurrogateRead1();
MemoryStream br=new MemoryStream(bb);
BinaryFormatter bf=new BinaryFormatter();
object o=bf.Deserialize(br);
sds = (DataSetSurrogate) o;
dataSet1 = sds.ConvertToDataSet();
dataGrid1.DataSource=dataSet1.Tables[0];
br.Close();
/// <summary>
/// 二进制序列化
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static byte[] SerializeBinary(object[] obj)
{
if(obj == null || obj.Length ==0)
return new byte[]{} ; for (int i=0; i<obj.Length; i++)
{
if (obj[i]!=null && obj[i] is DataSet)
{
obj[i] = new DataSetSurrogate((DataSet)obj[i]);
}
} BinaryFormatter se =new BinaryFormatter();
MemoryStream memStream = new MemoryStream();
se.Serialize(memStream, obj);
byte[] bobj = memStream.ToArray();
memStream.Close();
return bobj;
}
/// <summary>
/// 二进制反序列化
/// </summary>
/// <param name="bobj"></param>
/// <returns></returns>
public static object[] DeserializeBinary(byte[] bobj)
{
if(bobj==null || bobj.Length == 0)
return new object[]{} ; MemoryStream memStream = new MemoryStream(bobj);
memStream.Position = 0;
BinaryFormatter de =new BinaryFormatter();
object[] newobj = null;
newobj =(object[])de.Deserialize(memStream);
memStream.Close(); for (int i=0; i<newobj.Length; i++)
{
if (newobj[i]!=null && newobj[i] is DataSetSurrogate)
{
newobj[i] = ((DataSetSurrogate)newobj[i]).ConvertToDataSet();
}
} return newobj;
}
如果有,那就是在客户端,将byte[]反序列化成DataSet就会出错,是吗?我认为,这还是与反序列化部分相关。
客户端接受base64字符串再把它转为byte[]
把byte[]转为base64的代码如何实现?没搞过,帮助上也没搜到。谢谢了。
byte[] b = System.Convert.FromBase64String( str );
return System.Convert.ToBase64String( e );
客户端接收改成
byte [] bb = System.Convert.FromBase64String(this.ws.GetDsBytes());
还是报老错误-_-!!!
//未处理的“System.Runtime.Serialization.SerializationException”类型的异常出现在 mscorlib.dll 中。
//其他信息: 无法找到程序集 WebService1, Version=1.0.2227.16697, Culture=neutral, PublicKeyToken=null。
http://flyskywlh.cnblogs.com/archive/2005/08/18/217382.aspx
文章实现的。其中DataSetSurrogate类在
http://www.microsoft.com/taiwan/msdn/columns/adonet/AdoNet_20041231.htm
的demo下载文件里。而且button事件里的反序列化代码在webservice里另外写一个方法反序列化是可以的,放到winform里引用webservice后就出现找不到程序集的错误。
不但使用了DataSetSurregate,还使用了GZIP进行压缩,压缩后的数据一般不到以前的10%,效率非常高!
我还奇怪 sailhzr(sailhzr) 的回复,他的环境和运行过程和我的是一样的,但是他能成功,我反复重建项目好多次了,还是报错:(
至于提高性能,你可以用任何压缩解压方法,不菲的DataSetSurrogate。就用winzip提供的非托管代码或干脆lzw也会压缩的很好。
不过现在的移动设备都比较厉害的,比如11M的802.11b,传你这个纪录集顶多不过2000K/100k=20秒。倒是解压的话可能也要10秒的数量级。应该要权衡一下 压缩比、传输和解压速度。
1。异步调用webservice
2。少量多次传纪录,动态显示
//其他信息: 无法找到程序集 WebService1, Version=1.0.2227.16697, Culture=neutral, PublicKeyToken=null。在精简架构中的DataSetSurrogate要重新编译才行;
或者DataSetSurrogate中本身就存在精简架构不支持的序列化方法。
这是dotnet1.1的问题,
我以前建议的主要内容是要避开DataSet方法,传输过程中采用对象数组或自定义的压缩数据对象。
总之,精简架构是问题的根源,DataSetSurrogate到底是否可以在精简架构中使用,必须有它的原代码才能考证。另外,"mscorlib.dll",CE4.0与精简架构的兼容问题也是有的。
在以前的一个项目中,我考虑以上诸多因素,最终放弃了DataSet方法,采用对象数组。
只是建议,期待高人查出其中原因。
是否你的DLL有问题!如有需要,就加
就是前段时间做的测试,我是测试成功了!
是否你的DLL有问题!如有需要,我发一个给你!
------------
另外,"mscorlib.dll",CE4.0与精简架构的兼容问题也是有的。
------------让我考虑到的就是DataSetSurrogate的版本兼容问题会不会导致反序列化失败,其实是我犯了一个低级错误,就是我不是引用同一个DataSetSurrogate.dll来实现序列化反序列化,而是将DataSetSurrogate.cs直接放到服务器端和客户端的项目代码中,这样导致了2个DataSetSurrogate分别采用服务器端版本和客户端版本而导致版本不一致,反序列化失败,而将DataSetSurrogate分离出来单独做了一个类库项目,服务器端和客户端引用,就保持了一致,反序列化成功。至此问题解决。还有一点没搞明白就是,实际上反序列化的时候还没使用DataSetSurrogate类库功能,为什么反序列化直接就失败了呢object o = bf.Deserialize(br);//这里失败,程序中断DataSetSurrogate sds = (DataSetSurrogate)o;//这行才开始真正调用DataSetSurrogate类库将对象类型进行转换。序列化的机制还是没搞明白,唉,继续研究吧。结贴了,谢谢各位帮忙!!!