03 配置服務

03 配置服務

 http://www.cnblogs.com/easy5weikai/p/3825357.html

數據庫

生成數據庫腳本:

複製代碼
CREATE DATABASE [EmployeeDb];

CREATE TABLE [dbo].[T_Employee](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [Job] [nvarchar](50) NOT NULL,
    [Salary] [float] NOT NULL,
    [Dept] [nchar](10) NULL,
) ;
複製代碼

  Employee.cs

 View Code

 

數據訪問EmployeeDAL.cs

複製代碼
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using Keasy5.WCF.Imin.Chart06.DTO;

namespace Keasy5.WCF.Imin.Chart06.DAL
{
    public class EmployeeDAL
    {
        private const string ConnectingString =
            "Data Source=.;Initial Catalog=EmployeeDb;Integrated Security=True;Pooling=False";

        public IEnumerable<Employee> GetEmployees()
        {
            using (var sqlConnection = new SqlConnection(ConnectingString))
            {
                List<Employee> result = new List<Employee>();
                Employee employee = null;
                string sqlQuery = "Select * from T_Employee;";
                DataTable dataTable = new DataTable();
                SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlQuery, sqlConnection);

                sqlDataAdapter.Fill(dataTable);

                for (int i = 0; i < dataTable.Rows.Count; i++)
                {
                    employee = new Employee();
                    employee.Id = Convert.ToInt32(dataTable.Rows[i]["Id"]);
                    employee.Name = Convert.ToString(dataTable.Rows[i]["Name"]);
                    employee.Job = Convert.ToString(dataTable.Rows[i]["Job"]);
                    employee.Salary = Convert.ToDouble(dataTable.Rows[i]["Salary"]);
                    employee.Dept = Convert.ToString(dataTable.Rows[i]["Dept"]);

                    result.Add(employee);
                }

                return result;
            }
        }

        public void AddEmployee(Employee employee)
        {
            using (var sqlConnection = new SqlConnection(ConnectingString))
            {
                sqlConnection.Open();

                using (SqlCommand command = sqlConnection.CreateCommand())
                {
                    StringBuilder insertSql = new StringBuilder();
                    insertSql.Append("insert into T_Employee values(@Name,@Job,@Salary,@Dept)");

                    command.CommandType = CommandType.Text;
                    command.CommandText = insertSql.ToString();

                    command.Parameters.Add(new SqlParameter("@Name", employee.Name));
                    command.Parameters.Add(new SqlParameter("@Job", employee.Job));
                    command.Parameters.Add(new SqlParameter("@Salary", employee.Salary));
                    command.Parameters.Add(new SqlParameter("@Dept", employee.Dept));

                    command.ExecuteNonQuery();
                }
            }
        }
    }
}
複製代碼

 

 

 WCF的定義

服務接口IService1

複製代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
using System.Data;
using System.Data.SqlClient;

using Keasy5.WCF.Imin.Chart06.DTO;

namespace Keasy5.WCF.Imin.Chart06.Pro02
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        IEnumerable<Employee> GetEmployees();

        [OperationContract]
        void AddEmployee(Employee employee);

    }
}
複製代碼

 

服務實現類Service1.cs

 View Code

 

WCF服務端的配置

  一個最基本的服務(宿主)端配置如下:

複製代碼
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name ="Keasy5.WCF.Imin.Chart06.Pro02.Service1"
               behaviorConfiguration="testBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:5555"/>
          </baseAddresses>
        </host>
        <endpoint address =""
                  binding="wsHttpBinding"
                  contract="Keasy5.WCF.Imin.Chart06.Pro02.IService1">
        </endpoint>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="testBehavior">
          <serviceMetadata  httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>
複製代碼

 

 View Code

 

   

  宿主選擇WinForm,服務的開啓和關閉如下代碼所示:

  其中創建宿主的ServiceHost類的構造函數:

複製代碼
        //
        // 摘要: 
        //     使用服務的類型及其指定的基址初始化 System.ServiceModel.ServiceHost 類的新實例。
        //
        // 參數: 
        //   serviceType:
        //     承載服務的類型。
        //
        //   baseAddresses:
        //     System.Uri 類型的數組,包含承載服務的基址。
        //
        // 異常: 
        //   System.ArgumentNullException:
        //     serviceType 爲 null。
        public ServiceHost(Type serviceType, params Uri[] baseAddresses);
複製代碼

第二個參數是可變參數類型:所以可以參入基於不同協議的Uri,

Uri = “net.TCP://localhost/....”

Uri = "http://....."

Uri = "net.pipe://。。。"

。。。。

 傳入這些Uir基地址,實現同一服務,可同時提供多種協議的服務:

複製代碼
            //地址
            Uri pipeaddress = new Uri("net.pipe://localhost/NetNamedPipeBinding");
            Uri tcpaddress = new Uri("net.tcp://localhost:8088/TcpBinding");

            //服務宿主對象
            host = new ServiceHost(typeof(WcfServiceLibrary1.Service1), pipeaddress, tcpaddress);

            //綁定
            NetNamedPipeBinding pb = new NetNamedPipeBinding();
            NetTcpBinding tp = new NetTcpBinding();
複製代碼

或者使用配置文件進行配置:

複製代碼
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="WcfServiceLibrary1.Service1" behaviorConfiguration="textBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8088/tcpBinding"/>
            <add baseAddress="http://localhost:3200/httpBinding"/>
            <add baseAddress="net.pipe://localhost/pipeBinding"/>
          </baseAddresses>
        </host>
        <endpoint address="tcpmex" binding="mexTcpBinding" contract="IMetaExchange"></endpoint>
        <endpoint address="pipemex" binding="mexNamedPipeBinding" contract="IMetaExchange"></endpoint>

        <endpoint address="" binding="wsHttpBinding" contract="WcfServiceLibrary1.IService1"></endpoint>
        <endpoint address="" binding="netTcpBinding" contract="WcfServiceLibrary1.IService1"></endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="textBehavior">
          <serviceMetadata/>
          <serviceDebug/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>
複製代碼

 

 

 

客戶端調用WCF服務

 

客戶端調用WCF服務,需要一個WCF服務的代理類;

       獲取該代理類的方法有幾種:

       【1】在客戶端的項目中引用服務的方式    

    添加服務引用時自動生成的服務代理時自動生成的EndPiont

          <!--添加服務引用時自動生成的服務代理時自動生成的EndPiont-->
          <endpoint address="http://127.0.0.1:9999/Easy5WCFService" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_CalcutorService" contract="CalcutorWCFService.CalcutorService"
                name="BasicHttpBinding_CalcutorService" />
複製代碼
            //方法1:使用添加服務引用時自動生成的服務代理(這時,自動生成app.config)
            //此法用的代理服務命名空間的類型
            using (CalcutorWCFService.CalcutorServiceClient proxy = new CalcutorWCFService.CalcutorServiceClient())
            {
                double x  = Convert.ToDouble(this.textBox1.Text);
                double y = Convert.ToDouble(this.textBox2.Text);

                this.textBox3.Text = Convert.ToString(proxy.Add(x, y));
            }
複製代碼

 

       【2】手工生成代理類,這種又有很多種方式:

      2.1  ChannelFactory<T>

              使用ChannelFactory<T>的好處是支持泛型。

複製代碼
            //此法需要:自己動手添加app.config
            using (ChannelFactory<Contract.ICalcuator> channelFactory = new ChannelFactory<Contract.ICalcuator>("calcutorService"))//calcutorService爲配置文件(app.config)中的endpoint的Name屬性
            {
                Contract.ICalcuator calcuator = channelFactory.CreateChannel();

                double x = Convert.ToDouble(this.textBox1.Text);
                double y = Convert.ToDouble(this.textBox2.Text);

                this.textBox3.Text = Convert.ToString(calcuator.Add(x, y));
            }
複製代碼
    需要手工在app.config文件中添加endPoint節點配置:
          <!--自己動手寫服務代理時,需要手動添加的EndPoint-->
          <endpoint address="http://127.0.0.1:9999/Easy5WCFService" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_CalcutorService" contract="Contract.ICalcuator"
                name="calcutorService" />

 

          ChannelFactory<T>的構造函數有多個重載,也可以按如下方式創建:

複製代碼
            using (ChannelFactory<Contract.ICalcuator> channelFactory = new ChannelFactory<Contract.ICalcuator>(new BasicHttpBinding(), "http://127.0.0.1:9999/Easy5WCFService"))
            {
                Contract.ICalcuator calcuator = channelFactory.CreateChannel();

                double x = Convert.ToDouble(this.textBox1.Text);
                double y = Convert.ToDouble(this.textBox2.Text);

                this.textBox3.Text = Convert.ToString(calcuator.Add(x, y));
            }
複製代碼

  但是,這種方式是硬編碼方式,靈活性不好,不推薦。

 

    2.2 使用svcutil.exe工具生成代理類:

     WCF的服務元數據(Metadata),遵循Web服務描述語言(WSDL)標準,所以支持多種編程語言,處理WCF的svcutil.exe外,

java程序員也可以使用諸如WSDL2Java工具生成Java語言的客戶端代理類。

              下面介紹使用svcutil.exe生成C#語言的代理類:

              第一步:公開WCF服務的元數據信息

       方法一: 通過<serviceMetadata httpGetEnabled="true"/>公開,如下所示

複製代碼
  <system.serviceModel>
    <services>
      <service name ="Keasy5.WCF.Imin.Chart06.Pro02.Service1"
               behaviorConfiguration="testBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:5555"/>
          </baseAddresses>
        </host>
        <endpoint address =""
                  binding="wsHttpBinding"
                  contract="Keasy5.WCF.Imin.Chart06.Pro02.IService1">
        </endpoint>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="testBehavior">
          <serviceMetadata  httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
複製代碼

        方法二: 通過EndPoint端點的方式進行公開,在服務的配置文件中添加如下配置

複製代碼
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name ="Keasy5.WCF.Imin.Chart06.Pro02.Service1"
               behaviorConfiguration="testBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:5555"/>
          </baseAddresses>
        </host>
        <endpoint address =""
                  binding="wsHttpBinding"
                  contract="Keasy5.WCF.Imin.Chart06.Pro02.IService1">
        </endpoint>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetatadaExchange">
        </endpoint>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="testBehavior">
          <serviceMetadata  httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>
複製代碼

 

 

        公開WCF服務的元數據信息後就可以在瀏覽器中輸入:http://localhost:5555 就可以查看WCF服務信息。

              第二步:

        打開【VS2013 開發人員命令提】,輸入:

            svcutil.exe http://localhost:5555/?wsdl

 

自動生成的文件:

Service1.cs是生成的代理類 

 View Code

 

output.config是配置文件

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IService1" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:5555/" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IService1" contract="IService1"
                name="WSHttpBinding_IService1">
                <identity>
                    <userPrincipalName value="easy5-PC\easy5" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>
複製代碼

 

   現在用在項目中引用服務的方式添加代理,客戶端如下調用代理:

複製代碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Keasy5.WCF.Chart06.Pro02.Client.ServiceReference1;
using Keasy5.WCF.Imin.Chart06.DTO;

namespace Keasy5.WCF.Chart06.Pro02.Client
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IService1 proxService1 = new Service1Client();
            Employee newEmployee = new Employee()
            {
                Name = "Jack",
                Job = "Killer",
                Salary = 1000000,
                Dept = "N/A"
            };

            proxService1.AddEmployee(newEmployee);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            IService1 proxService1 = new Service1Client();

            IEnumerable<Employee> employees = proxService1.GetEmployees();
            this.dataGridView1.DataSource = employees;
        }
    }
}
複製代碼

 

本文代碼下載:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章