当数据量很大时,想要从服务端传到客户端可能会遇到这几个问题:基础连接意外关闭;内存溢出;或时间过长。
下面是我在项目中实现客户端导出txt文件时解决方法。txt有150M左右。
namespace XSGLSRV900 //服务端接口实现 { public class XSGLService : IXSGLService { //这些变量只能是静态的,如果是非静态的,在客户端每一次调用服务端都认为是新建一个服务对象,这些值将不再能读取到。关于WCF服务端的三种模式可参考http://www.cnblogs.com/tyb1222/archive/2012/10/12/2721252.html
//这样静态的是有缺陷的,对所有客户端建立的服务端都用这些静态变量,一旦某一个用户使其值改变即便前一个用户还没读取完List值也是不管的,没找到更好的解决办法 private static List<StringBuilder> LStringBuilder = new List<StringBuilder>(); private static int Count = 0; private static int Cur_INX = 0; public int BFBHDDSQLQuery_txt(string sSQL,ref List<string>Datas ,ref List<String> OutERROR) { int iERROR = 0; DataSet ds = null; List<string> exERROR = new List<string>(); //这里要使用StringBuilder,不能用string类型的,以为没对string进行一次操作都会在内存中新建一个对象,如果频繁操作很费时间。 //这里在new时需要用带餐的构造函数,否则默认的长度不够 StringBuilder ss = new StringBuilder(100, Int32.MaxValue); LStringBuilder = new List<StringBuilder>(); Datas = new List<string>(); int iCount = 0; Count = 0; Cur_INX = 0; DbConnection conn = bf.srv.framework.bflib.PubData.GetDbConnection(BHServerPlatform.iBFBHDD); try { CyQuery query = new CyQuery(conn); try { //这里加" " tab键实现txt对齐,再从txt转换成excel时也能保证对其 ss.Append("交易时间 ");//交易时间 ss.Append("结账日期 ");//结账日期 ss.Append("交易流水号 ");//交易流水号 ss.Append("部门代码 ");//部门代码 ss.Append("商标 ");//商标 ss.Append("商品代码 ");//商品代码 ss.Append("收款方式 ");//收款方式 ss.Append("收款金额 ");//收款金额 ss.Append("收款台号 ");//收款台号 ss.Append(" "); query.SQL.Text = sSQL; query.SQL.Text = sSQL; query.Open(); while (!query.Eof) //当Query是IsEmpty时,不能取值 { ss.Append( query.Fields[0].AsDateTime.ToString()+" ");//交易时间 ss.Append(query.Fields[1].AsDateTime.ToShortDateString() + " ");//结账日期 ss.Append(query.Fields[2].AsInteger.ToString() + " ");//交易流水号 ss.Append(query.Fields[3].AsString + " ");//部门代码 ss.Append(query.Fields[4].AsInteger.ToString() + " ");//商标 ss.Append(query.Fields[5].AsString.ToString() + " ");//商品代码 ss.Append(query.Fields[6].AsInteger.ToString() + " ");//收款方式 ss.Append(query.Fields[7].AsDecimal.ToString() + " ");//收款金额 ss.Append(query.Fields[8].AsString + " ");//收款台号 ss.Append( " "); iCount += 1; //这里要把字符串分开成若干个,否则在服务端往客户端传输时会因为数据量太大而报错,连接意外关闭,分成若干个,在客户端一段段读取不会有这个问题就 if (iCount %100000==0) { Count++; LStringBuilder.Add(ss); //Datas.Add(ss.ToString()); //ss.Clear(); ss = new StringBuilder(100, Int32.MaxValue); } query.Next(); } if (iCount % 100000 != 0) { Count++; LStringBuilder.Add(ss); //ss.Clear(); ss = new StringBuilder(100, Int32.MaxValue); } if (iCount > 0) { //chars = new char[ss.Length]; //ss.CopyTo(0, chars, 0, ss.Length); } query.Close(); } catch (Exception e) { iERROR = 1; BHServerPlatform.WriteErrorLog(e.GetType().ToString() + "," + e.StackTrace + ":" + query.SqlText); exERROR.Add(e.Message); } } catch (Exception e) { iERROR = 1; exERROR.Add(e.Message); } finally { conn.Close(); } OutERROR = exERROR; return iERROR; } public String GetStringBuilder() { if (Cur_INX < Count) { Cur_INX++; return LStringBuilder[Cur_INX-1].ToString(); } else return ""; } public bool GetString() { if (Cur_INX < Count) { return true; } else return false; } }
}
private void btn_DC_Click(object sender, RoutedEventArgs e)//客户端实现导出txt { Microsoft.Win32.SaveFileDialog MysaveFileDialog = new Microsoft.Win32.SaveFileDialog(); string MyExpName = "txt"; string fileName = txt_DC.Text.Trim(); string strPath = Environment.CurrentDirectory; MysaveFileDialog.DefaultExt = MyExpName;//默认扩展名 MysaveFileDialog.AddExtension = true;//是否自动添加扩展名 MysaveFileDialog.Filter = "*." + MyExpName + "|." + MyExpName; MysaveFileDialog.OverwritePrompt = true;//文件已存在是否提示覆盖 MysaveFileDialog.FileName = fileName; //dialogOpenFile.FileName = "文件名";//默认文件名 MysaveFileDialog.CheckPathExists = true;//提示输入的文件名无效 MysaveFileDialog.Title = "对话框标题"; //显示对话框 bool? b = MysaveFileDialog.ShowDialog(); if (b == true)//点击保存 { fileName = MysaveFileDialog.FileName; txt_DC.Text = fileName; //恢复系统路径-涉及不到的可以去掉 Environment.CurrentDirectory = strPath; } else { //恢复系统路径-涉及不到的可以去掉 Environment.CurrentDirectory = strPath; return; } List<string> Datas = new List<string>(); try { if (true)//(File.Exists(fileName)) { string sSQL = MakeSQL(); List<string> ERR = new List<string>(); int iRe = MyXSGLService.BFBHDDSQLQuery_txt(sSQL, ref Datas, ref ERR); if (iRe != 0) { PubData.bflibShowError(Application.Current.MainWindow, ERR); return; } else { Stream stream = MysaveFileDialog.OpenFile(); while (MyXSGLService.GetString()) { Byte[] fileContent = System.Text.Encoding.GetEncoding("gb2312").GetBytes(MyXSGLService.GetStringBuilder()); stream.Write(fileContent, 0, fileContent.Length); } stream.Close(); MessageBox.Show("导出完成!"); } } } catch (Exception ex) { MessageBox.Show(ex.Message); } }