wcf系列学习5天速成——事务的使用
摘抄自:http://www.cnblogs.com/huangxincheng/archive/2011/11/06/2238273.html
事务简单的一句话介绍:顺利执行就录入到数据库,如果中途出现异常就回滚到初始值,确保数据的正确性和防止冗余
在B2B的项目中,一般用户注册后,就有一个属于自己的店铺,此时,我们要插入两张表,User和Shop表。
当然要补录入成功,要不全失败
先晒项目结构:
第二步: 新建newdata数据库,用EF去映射,然后新建serviceWCF类库
这里有一点需要注意,在确保数据的正确性的同时,必须要保证数据库映射类型一样:
第三步:新建一个Model类库。建立两个实体类Shop和User,当然自定义类型在WCF中传输,
必须在类上加上【DataContract】,属性上加【DataMember】。
第四步:然后在ServiceWCF类库中新建两个文件Seller.cs 和 ISeller.cs.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace TransactionWcf
{
public class Seller : ISeller
{
public bool Add(Model.User user, out int userID)
{
using (NewDataEntities db = new NewDataEntities())
{
try
{
User userModel = new User()
{
UserName = user.UserName,
Passwrod = user.Password
};
db.AddToUser(userModel);
db.SaveChanges();
userID = userModel.UserID;
return true;
}
catch (Exception)
{
userID = 0;
throw;
}
}
}
public bool Add(Model.Shop shop, out int shopID)
{
using (NewDataEntities db = new NewDataEntities())
{
try
{
Shop shopModel = new Shop()
{
ShopName = shop.ShopName,
ShopUrl = shop.ShopUrl,
UserID = shop.UserID
};
db.AddToShop(shopModel);
db.SaveChanges();
shopID = shopModel.ShopID;
return true;
}
catch (Exception)
{
shopID = 0;
throw;
}
}
}
///<summary>
/// 录入用户和商店
///</summary>
///<param name="user"></param>
///<param name="shop"></param>
///<returns></returns>
//TransactionScopeRequired=true 告诉serviceHost自托管服务,进入我的方法,必须给我加上事务
//TransactionAutoComplete方法执行中,如果没有抛出异常,则自动提交
[OperationBehavior(TransactionScopeRequired=true,TransactionAutoComplete=true)]
public bool Add(Model.User user, Model.Shop shop)
{
int shopID;
int UserID;
//注意,这个方法操作了两个数据实例,为addUser和addShop。所以晋升为分布式服务
if (Add(user, out UserID))
{
//注意注意,我在Adduser成功的情况下,抛出异常,看是否回滚。
throw new Exception();
shop.UserID = UserID;
return Add(shop, out shopID);
}
return false;
}
}
}
第五步: 新建Host来承载了,配置AppConfig,这些细节就不再说了。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Host.Service1Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service
behaviorConfiguration="Host.Service1Behavior"
name="TransactionWcf.Seller">
<endpoint address=""
binding="wsHttpBinding"
contract="TransactionWcf.ISeller">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/ISeller/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
<connectionStrings>
<add name="NewDataEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="Data Source=WUXUELEI\SQLEXPRESS;Initial Catalog=NewData;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
承载服务:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace Host
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(TransactionWcf.Seller)))
{
host.Opened += delegate
{
Console.WriteLine("wcf服务已经启动");
};
host.Open(); //开启服务
Console.ReadLine();
}
}
}
}
至此我们的服务端已经建立好了...先用wcftestclient测试下试试看:
好,下面建立客户端:
第六步:开启WCF服务,新建ServiceClient类库,然后用信道生成实例。
先添加服务引用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace ServiceClient
{
class Program
{
static void Main(string[] args)
{
//创建实例对象
var user = new ServiceIsell.User()
{
UserName="huaying520",
Password="I Can Fly"
};
var shop = new ServiceIsell.Shop()
{
ShopName="小吴的店铺",
ShopUrl="http://www.baidu.com"
};
var factory = new ChannelFactory<ServiceIsell.ISellerChannel>(new WSHttpBinding(),new EndpointAddress("http://localhost:8732/Design_Time_Addresses/ISeller/")); //先创建信道
var client = factory.CreateChannel(); //创建客户端
if (client.Add(user, shop))
{
Console.WriteLine("您的店铺已经成功录入");
}
else
{
Console.WriteLine("不好意思,您的店铺有问题");
}
Console.ReadLine();
}
}
}
最后就是测试了:
首先:走正常流程。client.Add方法调用服务器端,运行效果如图所示:
是的,数据已经正常插入成功,对Client端而言,这个操作是透明的。
然后: 我们在Seller类中的Add方法中故意加入异常。看效果咋样。
然后运行客户端的时候:
说明是已经检测到咱们新建立的异常了...看数据库有没有新加数据...咱select下:
果然如我所料..此处没有录入新数据...说明咱的事物是成功的!
当然为了确保这个客户端抛出的异常是来自咱新建立的Expection...把客户端bug查看开启:
运行下看看:
呵呵...看到了..就是咱们新建立的new Exception导致的.....