IIS上のWCFサービスを経由してSQL Serverからデータを取得する際のメモ
WCFとは『Windows Communication Foundation』の略称で、分散システムを実現するためにMicrosoft が策定した通信フレームワークとのことです。最初は設定など色々めんどくさいですが、慣れれば非常簡単に、分散システムが実現できます。
1.WCFサービスプロジェクトの作成
まず最初に、Visual Studioで、WCFサービスのプロジェクトを作成する。
WCFサービスでは、どのようなサービスを提供するのか、また交換すべきデータは何なのかなどを定義する。
このようなサービスの定義は、ソース・コード上で属性(Attribute)を利用して記述する。
以下は何を提供するかを記述したインターフェースの定義。クライアントでもこのメソッドを利用する。
1 2 3 4 5 6 7 8 9 10 11 12 |
namespace KintaiWcfService.Service { using System; using KintaiWcfService.Dto; using System.ServiceModel; [ServiceContract(Namespace = "http://KintaiWcfService.Service.KintaiService")] public interface IKintaiService { [OperationContract] KintaiDto GetDataTable(string table); } } |
以下はサーバー側の実装クラス。今回はSQL Serverのデータを抽出して、クライアントに返却している。
ソースでは、DataTable.TableNameを設定しているが、これがなければ、WCFサービスが利用できない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
namespace KintaiWcfService.Service { using System; using System.Configuration; using System.Reflection; using System.Linq; using System.Text; using System.ServiceModel; using System.Data; using System.Data.SqlClient; using KintaiWcfService.Dto; using log4net; [ServiceBehavior(IncludeExceptionDetailInFaults = true)] public class KintaiService : IKintaiService { public virtual KintaiDto GetDataTable(string table) { var dto = new KintaiDto(); dto.DataTable = new DataTable(); dto.DataTable.TableName = table; var connectString = ConfigurationManager.AppSettings["connect.string"]; using (var con = new SqlConnection(connectString)) { using (var adapter = new SqlDataAdapter()) { string query = "SELECT * FROM " + table; adapter.SelectCommand = new SqlCommand(query, con); adapter.Fill(dto.DataTable); } } return dto; } } } |
以下はsvcファイル。サービスの内容を記述するが、今回は別ファイル(KintaiServiceクラス)に記述している。
1 |
<%@ ServiceHost Language="C#" Debug="true" Service="KintaiWcfService.Service.KintaiService" %> |
2.WCFサービスの配備
上記で作成したプロジェクトを、IISに配備する。まず最初にIIS上でアプリケーションを追加する。
そのあと、WCFサービスが利用できるように、ハンドラ―マッピングを起動して、svcが有効になっていることを確認する。
3.クライアントのプロジェクトの作成
クライアントのプロジェクトは、上記WCFサービスのプロジェクトを参照しプロジェクトを作成する。
今回は、Windowsフォームアプリのプロジェクトにした。
注意点は、サービスクラスの作成方法である。クライアント側では、サーバー側のKintaiServiceクラスではなくChannelFactoryクラスが生成したクラスを利用する。
また、今回はデータベースの全データを抽出するため、MaxReceivedMessageSizeの設定を行っている。この設定が行っていないと受信データ容量不足で例外が発生する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
using KintaiWcfService.Service; using System; using System.Configuration; using System.ServiceModel; using System.Windows.Forms; using System.Data; using System.Data.SqlClient; using log4net; using System.Reflection; namespace KintaiWcfClient { public partial class Form1 : Form { protected IKintaiService svcKintai; public Form1() { InitializeComponent(); this.svcKintai = (IKintaiService)this.CreateService(typeof(KintaiService)); } private object CreateService(Type stype) { var uri = "http://XXXXXXXX/KintaiWcfService/"; var address = new EndpointAddress(uri + stype.Name + ".svc"); var itype = stype.GetInterfaces()[0]; var ftype = typeof(ChannelFactory<>).MakeGenericType(itype); var binding = new BasicHttpBinding(BasicHttpSecurityMode.None); binding.MaxReceivedMessageSize = 2147483647; var factory = (ChannelFactory)Activator.CreateInstance(ftype, new object[] { binding, address }); var method = factory.GetType().GetMethod("CreateChannel", new Type[0]); var service = method.Invoke(factory, new object[] { }); return service; } private void button1_Click(object sender, EventArgs e) { var dto = this.svcKintai.GetDataTable(this.textBox1.Text); this.dataGridView1.DataSource = dto.DataTable; } } } |