[WCF Step by Step 读书笔记] Chapter01 WCF 介绍
下面通过搭建一个书中完整的WCF的例子阐述WCF:
1. 建立一个ASP.NET WebSite的的空工程ProductService。
2. 添加一个Class Library的工程,删除其.cs文件,添加一个ADO.NET Entity Model,从数据库选择AdventureWorks数据库,用到的两张表为Product和ProductInventory。其余使用默认值。
3. 在ProductService工程里添加对第二步Class Library的引用。
4. 在ProductService空工程里添加WCF Service项。这个时候,我们会发现项目里多了一个App_Code文件夹,里面存放着IService.cs和Service.cs两个文件,同时多出了一个Service.svc的文件。
5. 将IService.cs和Service重命名为IProductService和ProductService。
6. IProductService的内容为:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;namespace Products
{
// Data contract describing the details of a product passed to client applications
[DataContract]
public class ProductData
{
[DataMember]
public string Name;[DataMember]
public string ProductNumber;[DataMember]
public string Color;[DataMember]
public decimal ListPrice;
}// Service contract describing the operations provided by the WCF service
[ServiceContract]
public interface IProductsService
{
// Get the product number of every product
[OperationContract]
List<string> ListProducts();// Get the details of a single product
[OperationContract]
ProductData GetProduct(string productNumber);// Get the current stock level for a product
[OperationContract]
int CurrentStockLevel(string productNumber);// Change the stock level for a product
[OperationContract]
bool ChangeStockLevel(string productNumber, short newStockLevel, string shelf, int bin);
}
}这里对WCF Service可以提供的方法和数据类型进行了定义。WCF的runtime在收到相应的请求的Message以后,可以将其中内容传递给这些标注了[OperationContract]的方法,而返回操作时,也可以将结果通过runtime打包到message里返回。
[ServiceContract]表明这是这个类是用来提供WCF的Runtime需要运行的类。而[OperationContract]则是这个Runtime所能执行到方法。这两个Attribute都位于System.ServiceModel名空间里面。
而[DataContract]和[DataMember]用于对需要在Host和Client之间进行传递的数据对象的类型进行定义。他们位于System.Runtime.Serialization名空间里面。可见DataContract修饰的是Class,而DataMember修饰的是Field。
7. ProductService的内容是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;using System.Data.Entity;
using ProductsEntityModel;namespace Products
{
// WCF service that implements the service contract
// This implementation performs minimal error checking and exception handling
public class ProductsServiceImpl : IProductsService
{
public List<string> ListProducts()
{
// Create a list for holding product numbers
List<string> productsList = new List<string>();try
{
// Connect to the AdventureWorks database by using the Entity Framework
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
// Fetch the product number of every product in the database
var products = from product in database.Products
select product.ProductNumber;productsList = products.ToList();
}
}
catch
{
// Ignore exceptions in this implementation
}// Return the list of product numbers
return productsList;
}public ProductData GetProduct(string productNumber)
{
// Create a reference to a ProductData object
// This object will be instantiated if a matching product is found
ProductData productData = null;try
{
// Connect to the AdventureWorks database by using the Entity Framework
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
// Find the first product that matches the specified product number
Product matchingProduct = database.Products.First(
p => String.Compare(p.ProductNumber, productNumber) == 0);productData = new ProductData()
{
Name = matchingProduct.Name,
ProductNumber = matchingProduct.ProductNumber,
Color = matchingProduct.Color,
ListPrice = matchingProduct.ListPrice
};
}
}
catch
{
// Ignore exceptions in this implementation
}// Return the product
return productData;
}public int CurrentStockLevel(string productNumber)
{
// Obtain the total stock level for the specified product.
// The stock level is calculated by summing the quantity of the product
// available in all the bins in the ProductInventory table.// The Product and ProductInventory tables are joined over the
// ProductID column.int stockLevel = 0;
try
{
// Connect to the AdventureWorks database by using the Entity Framework
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
// Calculate the sum of all quantities for the specified product
stockLevel = (from pi in database.ProductInventories
join p in database.Products
on pi.ProductID equals p.ProductID
where String.Compare(p.ProductNumber, productNumber) == 0
select (int)pi.Quantity).Sum();
}
}
catch
{
// Ignore exceptions in this implementation
}// Return the stock level
return stockLevel;
}public bool ChangeStockLevel(string productNumber, short newStockLevel,
string shelf, int bin)
{
// Modify the current stock level of the selected product
// in the ProductInventory table.
// If the update is successful then return true, otherwise return false.// The Product and ProductInventory tables are joined over the
// ProductID column.try
{
// Connect to the AdventureWorks database by using the Entity Framework
using (AdventureWorksEntities database = new AdventureWorksEntities())
{
// Find the ProductID for the specified product
int productID =
(from p in database.Products
where String.Compare(p.ProductNumber, productNumber) == 0
select p.ProductID).First();// Find the ProductInventory object that matches the parameters passed
// in to the operation
ProductInventory productInventory = database.ProductInventories.First(
pi => String.Compare(pi.Shelf, shelf) == 0 &&
pi.Bin == bin &&
pi.ProductID == productID);// Update the stock level for the ProductInventory object
productInventory.Quantity += newStockLevel;// Save the change back to the database
database.SaveChanges();
}
}
catch
{
// If an exception occurs, return false to indicate failure
return false;
}// Return true to indicate success
return true;
}
}
}这里是对IProductServic定义的方法的具体实现。
8. 在Service.svc里面将其内容改为:
<%@ ServiceHost Language="C#" Debug="true" Service="Products.ProductsServiceImpl" CodeBehind="~/App_Code/ProductsService.cs" %>
注意这里ServiceHost表明IIS将作为这个WCF的Runtime,提供的Service的具体内容是实现了Product.ProductServiceImpl这个类型,而这个类的代码在ProductsService.cs这个文件里面。
9. 在网站的web.config的配置文件里添加connectionString(这里的ConnectionString实际上可以直接从ClassLibrary工程的App.config直接拷贝过来):
<connectionStrings>
<add name="AdventureWorksEntities" connectionString="metadata=res://*/ProductsModel.csdl|res://*/ProductsModel.ssdl|res://*/ProductsModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=.\SQLExpress;Initial Catalog=AdventureWorks;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" /></connectionStrings>
注意这里metadata可能会发生链接错误的情况,这时候可以直接将其值改为metadata=res://*/,这样所有的assembly都会成为考虑对象。
10. 右键点击Service.svc运行,将浏览器出现的地址添加到WcfTestClient中,查看WCF提供的相应方法能否运行。
注意如果Visual Studio内的WCF能够运行,但是在IIS上部署以后从数据库得不到数据,注意查看应用程序池的Identity,查看其权限是否足够。

浙公网安备 33010602011771号