WCF 大数据量如何从服务端传到客户端

时间:2022-03-23 19:05:09

当数据量很大时,想要从服务端传到客户端可能会遇到这几个问题:基础连接意外关闭;内存溢出;或时间过长。

下面是我在项目中实现客户端导出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 { //这里加"\t" tab键实现txt对齐,再从txt转换成excel时也能保证对其 ss.Append("交易时间\t");//交易时间 ss.Append("结账日期\t");//结账日期 ss.Append("交易流水号\t");//交易流水号 ss.Append("部门代码\t");//部门代码 ss.Append("商标\t");//商标 ss.Append("商品代码\t");//商品代码 ss.Append("收款方式\t");//收款方式 ss.Append("收款金额\t");//收款金额 ss.Append("收款台号\t");//收款台号 ss.Append("\r\n"); query.SQL.Text = sSQL; query.SQL.Text = sSQL; query.Open(); while (!query.Eof) //当Query是IsEmpty时,不能取值 { ss.Append( query.Fields[0].AsDateTime.ToString()+"\t");//交易时间 ss.Append(query.Fields[1].AsDateTime.ToShortDateString() + "\t");//结账日期 ss.Append(query.Fields[2].AsInteger.ToString() + "\t");//交易流水号 ss.Append(query.Fields[3].AsString + "\t");//部门代码 ss.Append(query.Fields[4].AsInteger.ToString() + "\t");//商标 ss.Append(query.Fields[5].AsString.ToString() + "\t");//商品代码 ss.Append(query.Fields[6].AsInteger.ToString() + "\t");//收款方式 ss.Append(query.Fields[7].AsDecimal.ToString() + "\t");//收款金额 ss.Append(query.Fields[8].AsString + "\t");//收款台号 ss.Append( "\r\n"); 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);
            }
            
        }