我正在编写一个向客户端返回大量数据的服务。理想情况下,我想返回实体的 IEnumerable ,因为我希望服务和客户端都具有懒惰的性能优势。我还希望能够压缩流以减少带宽。
我能够将 IEnumerable 序列化为流并利用 GZip 来压缩它。我还能够成功地反序列化流。但是,我的实现并没有达到我目标的懒惰部分。
我已经阅读了类似于我的问题的概念解决方案,但它们都涉及返回 IEnumerable 的字节。理想情况下,我希望客户端接收实体的 IEnumerable ,并且能够在反序列化时返回它。
[DataContract]
public class Entity
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Code { get; set; }
[DataMember]
public string Description { get; set; }
}
[Test]
public void TestSerialEnumGzip()
{
var e = GetEnum();
var s = SerializeToStreamGzip(e);
Console.WriteLine($" TestSerialGzip stream size {s.Length}");
var b = DeserializeFromStreamGzip<IEnumerable<Entity>>(s);
}
private IEnumerable<Entity> GetEnum()
{
for (var x = 0; x < 10; ++x)
{
Console.WriteLine($"yielding {x}");
yield return new Entity { Id = x, Code = x.ToString(), Description = x.ToString() };
}
}
private Stream SerializeToStreamGzip<T>(T toSerialize)
{
var s = new MemoryStream();
using (var gz = new GZipStream(s, CompressionMode.Compress, true))
{
var ser = new DataContractSerializer(typeof(T));
ser.WriteObject(gz, toSerialize);
}
s.Seek(0, SeekOrigin.Begin);
return s;
}
private T DeserializeFromStreamGzip<T>(Stream stream)
{
var ser = new DataContractSerializer(typeof(T));
var gz = new GZipStream(stream, CompressionMode.Decompress);
var result = (T)ser.ReadObject(gz);
return result;
}
答案 0 :(得分:1)
我认为你可能对 IEnumerable 感到有点困惑。但是,除此之外,你真的应该把你的研究重点放在 WCF Streaming
上查看此博客Custom WCF Streaming及其相关的example。它基本上封装了您想要的所有内容,并使用BinaryFormatter
,
如果您想更进一步,可以使用协议缓冲区 Protobuf-net或添加自己的广告压缩。但是,我将这些细节留给您。
基本思想是:我们将有两个线程,一个线程将执行 复杂的数据库查询和另一个线程将数据库行流 客户。所以我们将改变数据库查询,使其返回 每次只有1000行。并修改WCF服务以流式传输这些 1000行到客户端。 WCF服务是将数据库行传输到 客户端,同时在不同的线程上,WCF服务将 再次运行数据库查询以获取下一个1000行。这样的方式 WCF服务完成将流行传输到客户端后,即可 下一组行可用于流式传输到客户端