WebService在.NET中的应用

提高WebService大数据量网络传输处理的性能

直接返回DataSet对象
特点:通常组件化的处理机制,不加任何修饰及处理;
优点:代码精减、易于处理,小数据量处理较快;
缺点:大数据量的传递处理慢,消耗网络资源;
建议:当应用系统在内网、专网(局域网)的应用时,或外网(广域网)且数据量在KB级时的应用时,采用此种模式。

        public DataSet GetDataSet()
        {
            string sql = "select * from XT_TEXT";
            SqlConnection conn = new SqlConnection("Server=xxxxx;DataBase=s168593;user id=s168593;password=h0y+FeC*;");
            conn.Open();
            SqlDataAdapter dataAd = new SqlDataAdapter(sql, conn);
            DataSet DS = new DataSet("XT_TEXT");
            dataAd.Fill(DS);
            conn.Close();
            return DS;
        }

Client:

        private void BindDataSet(DataSet DS)
        {
            this.dataGridView1.DataSource = DS.Tables[0];
        }

        private void button1_Click(object sender, EventArgs e)
        {
            com.dzbsoft.www.DataSetService ds = new Test.com.dzbsoft.www.DataSetService();
            DateTime dtBegin = DateTime.Now;
            DataSet DS = ds.GetDataSet();
            this.label1.Text = string.Format("耗时:{0}", DateTime.Now - dtBegin);
            BindDataSet(DS);
        }

返回DataSet对象用Binary序列化后的字节数组
特点:字节数组流的处理模式;
优点:易于处理,可以中文内容起到加密作用;
缺点:大数据量的传递处理慢,较消耗网络资源;
建议:当系统需要进行较大数据交换时采用。

        public byte[] GetDataSetBytes()
        {
            DataSet DS = GetDataSet();
            BinaryFormatter ser = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            ser.Serialize(ms, DS);
            byte[] buffer = ms.ToArray();
            return buffer;
        }

Client:

        private void button2_Click(object sender, EventArgs e)
        {
            com.dzbsoft.www.DataSetService ds = new Test.com.dzbsoft.www.DataSetService();
            DateTime dtBegin = DateTime.Now;
            byte[] buffer = ds.GetDataSetBytes();
            DataSet DS = ds.GetDataSet();
            BinaryFormatter ser = new BinaryFormatter();
            DataSet dataset = ser.Deserialize(new MemoryStream(buffer)) as DataSet;
            this.label2.Text = string.Format("耗时:{0}", DateTime.Now - dtBegin + "          " + buffer.Length.ToString());
            BindDataSet(DS);
        }

返回DataSetSurrogate对象用Binary序列化后的字节数组
特点:微软提供的开源组件;下载地址:http://support.microsoft.com/kb/829740/zh-cn
优点:易于处理,可以中文内容起到加密作用;
缺点:大数据量的传递处理慢,较消耗网络资源;
建议:当系统需要进行较大数据交换时采用。

        public byte[] GetDataSetSurrogateBytes()
        {
            DataSet DS = GetDataSet();
            DataSetSurrogate dss = new DataSetSurrogate(DS);
            BinaryFormatter ser = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            ser.Serialize(ms, dss);
            byte[] buffer = ms.ToArray();
            return buffer;
        } 

Client:

        private void button3_Click(object sender, EventArgs e)
        {
            com.dzbsoft.www.DataSetService ds = new Test.com.dzbsoft.www.DataSetService();
            DateTime dtBegin = DateTime.Now;
            byte[] buffer = ds.GetDataSetSurrogateBytes();
            BinaryFormatter ser = new BinaryFormatter();
            DataSet DS = ds.GetDataSet();
            DataSetSurrogate dss = ser.Deserialize(new MemoryStream(buffer)) as DataSetSurrogate;
            DataSet dataset = dss.ConvertToDataSet();
            this.label3.Text = string.Format("耗时:{0}", DateTime.Now - dtBegin + "          " + buffer.Length.ToString());
            BindDataSet(DS);
        } 

返回DataSetSurrogate对象用Binary序列化并Zip压缩后的字节数组
特点:对字节流数组进行压缩后传递;
优点:当数据量大时,性能提高效果明显,压缩比例大;
缺点:相比第三方组件,压缩比例还有待提高;
建议:当系统需要进行大数据量网络数据传递时,建议采用此种可靠、高效、免费的方法。

        public byte[] GetDataSetSurrogateZipBytes()
        {
            DataSet DS = GetDataSet();
            DataSetSurrogate dss = new DataSetSurrogate(DS);
            BinaryFormatter ser = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            ser.Serialize(ms, dss);
            byte[] buffer = ms.ToArray();
            byte[] Zipbuffer = Compress(buffer);
            return Zipbuffer;
        }

        public byte[] Compress(byte[] data)
        {
            MemoryStream ms = new MemoryStream();
            Stream zipStream = null;
            zipStream = new GZipStream(ms, CompressionMode.Compress, true);
            zipStream.Write(data, 0, data.Length);
            zipStream.Close();
            ms.Position = 0;
            byte[] compressed_data = new byte[ms.Length];
            ms.Read(compressed_data, 0, int.Parse(ms.Length.ToString()));
            return compressed_data;
        } 

Client:

        private void button4_Click(object sender, EventArgs e)
        {
            com.dzbsoft.www.DataSetService ds = new Test.com.dzbsoft.www.DataSetService();
            DateTime dtBegin = DateTime.Now;
            byte[] zipBuffer = ds.GetDataSetSurrogateZipBytes();
            byte[] buffer = UnZipClass.Decompress(zipBuffer);
            BinaryFormatter ser = new BinaryFormatter();
            DataSet DS = ds.GetDataSet();
            DataSetSurrogate dss = ser.Deserialize(new MemoryStream(buffer)) as DataSetSurrogate;
            DataSet dataset = dss.ConvertToDataSet();
            this.label4.Text = string.Format("耗时:{0}", DateTime.Now - dtBegin + "          " + zipBuffer.Length.ToString());
            BindDataSet(DS);
        } 
    public static class UnZipClass
    {
        /// <summary>
        /// Decompresses the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns></returns>
        public static byte[] Decompress(byte[] data)
        {
            try
            {
                MemoryStream ms = new MemoryStream(data);
                Stream zipStream = null;
                zipStream = new GZipStream(ms, CompressionMode.Decompress);
                byte[] dc_data = null;
                dc_data = ExtractBytesFormStream(zipStream, data.Length);
                return dc_data;
            }
            catch
            {
                return null;
            }
        }

        public static byte[] ExtractBytesFormStream(Stream zipStream, int dataBlock)
        {
            try
            {
                byte[] data = null;
                int totalBytesRead = 0;
                while (true)
                {
                    Array.Resize(ref data, totalBytesRead + dataBlock + 1);
                    int bytesRead = zipStream.Read(data, totalBytesRead, dataBlock);
                    if (bytesRead == 0)
                    {
                        break;
                    }
                    totalBytesRead += bytesRead;
                }
                Array.Resize(ref data, totalBytesRead);
                return data;
            }
            catch
            {
                return null;
            }
        }
    }

测试用例:SqlServer2000数据库,数据量大小40000行,字段数10个,结果如下:

使用方法 总用时(秒) 数据大小(byte)
大小百分比(%)

直接返回DataSet 12.625 19629414 100%
返回二进制序列化后DataSet 9.712 12049645 61.38%
返回转化DataSetSurrogate的DataSet并且二进制序列化后 7.943 5138990 26.18%
返回转化DataSetSurrogate的DataSet并且二进制序列化后使用zip压缩 7.619 978033 4.98%

WebService中的异步调用

调用WebService方法有两种方式,同步调用和异步调用。同步调用是程序继续执行前等候调用的完成,而异步调用在后台继续时,程序也继续执行,不必等待方法处理完成而直接返回。

同步模式:
优点:稳定、安全、可靠;
缺点:效率低下。
异步模式:
优点:高效、充分利用资源;
缺点:事务处理较为复杂,不易于控制。

下面的Demo是通过ado.net对数据库表导入导出的操作。

Host:

    public class AsynWebService : System.Web.Services.WebService
    {
        [WebMethod(Description = "复制表数据表数据库表")]
        public string CopyDataTable(string Pub_CnnD, string DestTableName, byte[] ZipByte)
        {
            byte[] buffer = UnZipClass.Decompress(ZipByte);
            BinaryFormatter ser = new BinaryFormatter();
            DataSetSurrogate dss;
            dss = (DataSetSurrogate)ser.Deserialize(new MemoryStream(buffer));
            DataSet DS = dss.ConvertToDataSet();
            int RowNum;
            RowNum = DS.Tables[0].Rows.Count;
            bool Result = DataTableFillToDb(Pub_CnnD, DestTableName, DS.Tables[0]);
            DS.Clear();
            DS.Reset();
            GC.Collect();
            if (Result == true)
            {
                return "复制表:" + DestTableName + " 的数据到远程数据成功!记录数为:" + RowNum.ToString();
            }
            else
            {
                return "复制表:" + DestTableName + " 的数据到远程数据失败!";
            }
        }

        /// <summary>
        /// 表存在的DataTable填充
        /// </summary>
        /// <param name="Pub_CnnD">数据库联结串</param>
        /// <param name="DestTableName">目标表名</param>
        /// <param name="SouseDataTable">源DataTable</param>
        /// <returns></returns>
        private bool DataTableFillToDb(string Pub_CnnD, string DestTableName, DataTable SouseDataTable)
        {
            try
            {
                if (SouseDataTable.Rows.Count > 0)
                {
                    SqlConnection SqlCnn = new SqlConnection(Pub_CnnD);
                    SqlCnn.Open();
                    DataTable NewTable = OrdinalTable(Pub_CnnD, SouseDataTable, SouseDataTable.TableName);
                    SqlBulkCopy Bcp = new SqlBulkCopy(SqlCnn);
                    Bcp.DestinationTableName = DestTableName;
                    Bcp.WriteToServer(NewTable);
                    Bcp.Close();
                    SqlCnn.Close();
                }
                SouseDataTable.Reset();
                SouseDataTable.Dispose();
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 调整表字段顺序
        /// </summary>
        /// <param name="SqlConnstring">数据库联结串</param>
        /// <param name="DTS">源DataTable</param>
        /// <param name="TableName">表名</param>
        /// <returns></returns>
        private DataTable OrdinalTable(string SqlConnstring, DataTable DTS, string TableName)
        {
            try
            {
                System.Data.SqlClient.SqlConnection SqldbCnn = new System.Data.SqlClient.SqlConnection(SqlConnstring);
                DataTable DTD = new DataTable();
                System.Data.SqlClient.SqlDataAdapter SqlDbDA = new System.Data.SqlClient.SqlDataAdapter("select top 1 * from " + TableName, SqldbCnn);
                SqldbCnn.Open();
                SqlDbDA.Fill(DTD);
                SqlDbDA.Dispose();
                SqldbCnn.Close();
                DTD.Clear();
                int I = 0;
                int J = 0;
                string CNS = "";
                string CND = "";
                int MaxCol = 0;
                for (I = 0; I <= DTS.Columns.Count - 1; I++)
                {
                    CNS = DTS.Columns[I].ColumnName;
                    for (J = 0; J <= DTD.Columns.Count - 1; J++)
                    {
                        CND = DTD.Columns[J].ColumnName;
                        if (CND.ToUpper() == CNS.ToUpper())
                        {
                            if (MaxCol < J)
                            {
                                MaxCol = J;
                                break;
                            }
                        }
                    }
                }
                for (J = 0; J <= MaxCol; J++)
                {
                    if (DTS.Columns.IndexOf(DTD.Columns[J].ColumnName) < 0)
                    {
                        DTS.Columns.Add(DTD.Columns[J].ColumnName.ToUpper(), DTD.Columns[J].DataType);
                    }
                }

                for (I = 0; I <= DTD.Columns.Count - 1; I++)
                {
                    CND = DTD.Columns[I].ColumnName;
                    for (J = 0; J <= DTS.Columns.Count - 1; J++)
                    {
                        CNS = DTS.Columns[J].ColumnName;
                        if (CNS.ToUpper() == CND.ToUpper())
                        {
                            DTS.Columns[J].SetOrdinal(I);
                            break;
                        }
                    }
                }
                return DTS;
            }
            catch
            {
                return DTS;
            }
        }

Client:

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }
        private string DestConnstring = "Server=60.28.25.58;DataBase=s168593;user id=s168593;password=h0y+FeC*;";
        private string SourceConnstring = "Server=.;DataBase=XZBWWW;user id=sa;password=sasa;";
        private void Form1_Load(object sender, EventArgs e)
        {
            SqlConnection Sconn = new SqlConnection(SourceConnstring);
            Sconn.Open();
            DataTable DT = new DataTable();
            DT = Sconn.GetSchema("Tables");
            this.listBox1.DisplayMember = "TABLE_NAME";
            this.listBox1.DataSource = DT;
            Sconn.Close();

        }

        private void listBox1_DoubleClick(object sender, EventArgs e)
        {
            localhost.AsynWebService Myservice = new Test.localhost.AsynWebService();
            Myservice.CopyDataTableCompleted += new Test.localhost.CopyDataTableCompletedEventHandler(CopyDataTableEventHandler);

            DataRowView DRV=(DataRowView)this.listBox1.Items[this.listBox1.SelectedIndex];
            DataSet DS=new DataSet();
            DS=GetDataSet(SourceConnstring,"select * from " + DRV["TABLE_NAME"].ToString());

            Myservice.CopyDataTableAsync(DestConnstring, DRV["TABLE_NAME"].ToString(), GetDataSetSurrogateZipBYtes(DS));
            this.textBox1.Text = this.textBox1.Text + "运行本模块完成!";

        }

        private void CopyDataTableEventHandler(object sender, localhost.CopyDataTableCompletedEventArgs e)
        {
            this.textBox1.Text = this.textBox1.Text + e.Result + System.Environment.NewLine;
        }

        public DataSet GetDataSet(string StrCnn, string StrSql)
        {
            DataSet DS = new DataSet();
            SqlDataAdapter DA = new SqlDataAdapter(StrSql, StrCnn);
            DA.Fill(DS);
            DA.Dispose();
            return DS;
        }

        public byte[] GetDataSetSurrogateZipBYtes(DataSet DS)
        {
            DataSetSurrogate dss = new DataSetSurrogate(DS);
            BinaryFormatter ser = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            ser.Serialize(ms, dss);
            byte[] buffer = ms.ToArray();
            byte[] Zipbuffer = Compress(buffer);
            return Zipbuffer;
        }
        private byte[] Compress(byte[] data)
        {
            MemoryStream ms = new MemoryStream();
            Stream zipStream = null;
            zipStream = new GZipStream(ms, CompressionMode.Compress, true);
            zipStream.Write(data, 0, data.Length);
            zipStream.Close();
            ms.Position = 0;
            byte[] Compressed_Data = new byte[ms.Length];
            ms.Read(Compressed_Data, 0, int.Parse(ms.Length.ToString()));
            return Compressed_Data;
        }
    }

动态调用WebService

代码文档对象模型CodeDom的使用和编程使用C#编译器

    public static class WebServiceHelper
    {
        /// <summary>
        /// 动态调用WebService
        /// </summary>
        /// <param name="url">WebService地址</param>
        /// <param name="methodname">方法名(模块名)</param>
        /// <param name="args">参数列表</param>
        /// <returns>object</returns>
        public static object InvokeWebService(string url, string methodname, object[] args)
        {
            return InvokeWebService(url, null, methodname, args);
        }
        /// <summary>
        /// 动态调用WebService
        /// </summary>
        /// <param name="url">WebService地址</param>
        /// <param name="classname">类名</param>
        /// <param name="methodname">方法名(模块名)</param>
        /// <param name="args">参数列表</param>
        /// <returns>object</returns>
        public static object InvokeWebService(string url, string classname, string methodname, object[] args)
        {
            string @namespace = "ServiceBase.WebService.DynamicWebLoad";
            if (classname == null || classname == "")
            {
                classname = GetClassName(url);
            }
            //获取服务描述语言(WSDL)
            WebClient wc = new WebClient();
            Stream stream = wc.OpenRead(url + "?WSDL");
            ServiceDescription sd = ServiceDescription.Read(stream);
            ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
            sdi.AddServiceDescription(sd, "", "");
            CodeNamespace cn = new CodeNamespace(@namespace);
            //生成客户端代理类代码
            CodeCompileUnit ccu = new CodeCompileUnit();
            ccu.Namespaces.Add(cn);
            sdi.Import(cn, ccu);
            CSharpCodeProvider csc = new CSharpCodeProvider();
            ICodeCompiler icc = csc.CreateCompiler();
            //设定编译器的参数
            CompilerParameters cplist = new CompilerParameters();
            cplist.GenerateExecutable = false;
            cplist.GenerateInMemory = true;
            cplist.ReferencedAssemblies.Add("System.dll");
            cplist.ReferencedAssemblies.Add("System.XML.dll");
            cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
            cplist.ReferencedAssemblies.Add("System.Data.dll");
            //编译代理类
            CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
            if (true == cr.Errors.HasErrors)
            {
                System.Text.StringBuilder sb = new StringBuilder();
                foreach (CompilerError ce in cr.Errors)
                {
                    sb.Append(ce.ToString());
                    sb.Append(System.Environment.NewLine);
                }
                throw new Exception(sb.ToString());
            }

            //生成代理实例,并调用方法
            System.Reflection.Assembly assembly = cr.CompiledAssembly;
            Type t = assembly.GetType(@namespace + "." + classname, true, true);
            object obj = Activator.CreateInstance(t);
            System.Reflection.MethodInfo mi = t.GetMethod(methodname);
            return mi.Invoke(obj, args);

        }

        private static string GetClassName(string url)
        {
            string[] parts = url.Split(‘/‘);
            string[] pps = parts[parts.Length - 1].Split(‘.‘);
            return pps[0];
        }

    }

Test WebService:

        [WebMethod]
        public string HelloWorld(string Temp1,string Temp2)
        {
            return "参数1:" + Temp1 + "  参数2:" + Temp2;
        } 

Client:

            string url = "http://localhost/InvokeService/Service1.asmx";
            string[] args = new string[2];
            args[0] = this.textBox1.Text;
            args[1] = this.textBox2.Text;

            object result = InvokeWebService.WebServiceHelper.InvokeWebService(url, "HelloWorld", args);
            this.textBox3.Text = result.ToString();
时间: 2024-10-12 21:16:32

WebService在.NET中的应用的相关文章

WebService之JDK中wsimport命令

1.编写WebService类,使用@WebService注解 package test; import javax.jws.WebService; @WebService public class HelloServiceImpl{ public String say(String name) { return "Hello "+name; } } WebService类 2.使用main方法发布WebService package test; import javax.xml.ws

cxf WebService设置wsdl中soapAction的值

用cxf开发一个WebService很简单,只需要下面几步: 1.定义接口 public interface HelloService { String hello(); } 2.实现 public class HelloServiceImpl implements HelloService { @Override public String hello() { return "hi,my name is gyoung "; } } 3.用ServerFactoryBean生成服务 p

.net webService保存全局变量中

遇到坑,然后找到解决方案,我就习惯做个记录. 情景:通过webservice调用一个第三方的库,在初始化第三方库的时候需要花费较长时间 目的:希望通过初始化一次,缓存下来,下次直接调用,而不必每次初始化. 处理思路:在web项目中添加全局应用程序类(Global.cs),通过其Application_Start事件完成初始化,初始化后保存到一个静态类文件的静态对象中,需要的时候从静态对象中获取. 技术预研: 预研一.使用字符串作为初始化的对象,达到预期目的,能存能取. 预研二.使用第三方对象作为

有WebService的项目中写applicationContex.xml文件时应注意!!!

这是一个简单的WebService实例,来看下如下的applicationContex.xml文件: 1.有XFire的配置 <bean id="baseWebService" class="org.codehaus.xfire.spring.remoting.XFireExporter" lazy-init="false" abstract="true"> <property name="serv

JAVA项目中公布WebService服务——简单实例

1.在Java项目中公布一个WebService服务: 怎样公布? --JDK1.6中JAX-WS规范定义了怎样公布一个WebService服务. (1)用jdk1.6.0_21以后的版本号公布. (2)与Web服务相关的类,都位于Javax.jws.*包中 @WebService--此注解用在类上指定将此类公布成一个WebService: EndPoint--此类为端点服务类,当中publish()方法用于将一个已经加入了@WebService注解对象绑定到一个地址的port上,用于公布. 2

FineReport中以jws方式调用WebService数据源方案

在使用WebService作为项目的数据源时,希望报表中也是直接调用这个WebService数据源,而不是定义数据连接调用对应的数据库表,这样要怎么实现呢? 在程序中访问WebService应用服务,将WebService返回的数据转为程序数据集,然后在设计器中调用. 以axis1.4上的WebService为例,介绍其取数方式以及将数据转换为WebService的程序数据集的过程. WebService应用服务 如在Tomcat下的Axis工程中以jwa方式发布了一个WebService应用服

JAVA项目中发布WebService服务——简单实例

1,在Java项目中发布一个WebService服务: 如何发布? --JDK1.6中JAX-WS规范定义了如何发布一个WebService服务: (1)用jdk1.6.0_21以后的版本发布: (2)与Web服务相关的类,都位于Javax.jws.*包中 @WebService--此注解用在类上指定将此类发布成一个WebService: EndPoint--此类为端点服务类,其中publish()方法用于将一个已经添加了@WebService注解对象绑定到一个地址的端口上,用于发布. 2,例子

WebService中的WSDL详解

WebService中的WSDL详解 有人在WebService开发的时候,特别是和第三方有接口的时候,走的是SOAP协议,然后用户(或后台)给你一个WSDL文件(或网址),说按照上面的进行适配, 这时就要对WebService的WSDL有一定的理解,本文将对WSDL(WebService描述语言)进行详细总结. WSDL (Web Services Description Language,Web服务描述语言)是一种XML Application,他将Web服务描述定义为一组服务访问点,客户端

微软 BI ssis 中的 script task中用代码直接调用 WCF / Webservice

背景: 在普通的C#项目中,可以直接调用 WCF / Webservice: 在微软BI的 ssis中,有 webservice任务组件,也可以直接调用简单的 WCF / Webservice; 偶这边的情况是,后端的 WCF中用的反射,所以在 ssis中的webservice任务组件中,死活不能识别 WCF对应的方法. 所以只能在ssis的 script task组件中,用纯代码的方式来调用WCF服务. 就这样,可能还是有问题:可能会碰到 不能识别 System.ServiceModel节点的