WCF之分布式事务一
来源:互联网 发布:网络词 抓马什么梗 编辑:程序博客网 时间:2024/05/21 13:58
当然,要么插入成功,要么全失败。
WCF的各种binding中,除了BasicHttpBinding,BasicHttpContextBinding,NetPeerTcpBinding之外,其他的binding都支持事务。
首先看一下项目结构图:
一、建立WCFModel
新建一个Model类库。建立两个实体类Shop和User,当然自定义类型在WCF中传输,
必须在类上加上【DataContract】,属性上加【DataMember】。
using System;using System.Collections.Generic;using System.Runtime.Serialization;namespace WCFModel{ [DataContract] public class User { [DataMember] public int UserID { get; set; } [DataMember] public String UserName { get; set; } [DataMember] public string Password { get; set; } [DataMember] public ICollection<Shop> Shop { get; set; } }}
using System.Collections.Generic;using System.ComponentModel.DataAnnotations.Schema;using System.Runtime.Serialization;namespace WCFModel{ [DataContract] public class Shop { [DataMember] public int ShopID { get; set; } [DataMember] public int UserID { get; set; } [DataMember] public string ShopName { get; set; } [DataMember] public string ShopUrl { get; set; } [DataMember] [ForeignKey("UserID")] public ICollection<User> Users { get; set; } }}
二、创建WCFService,并使用code first 创建数据库:
创建WCFService类库,通过nuget引用Entityframework包,并创建一个CommerceDBContext类,继承自DbContext:
using System.Data.Entity;using WCFModel;namespace WCFService{ public class CommerceDBContext:DbContext { public CommerceDBContext(string connectionString):base(connectionString) { new DropCreateDatabaseIfModelChanges<CommerceDBContext>().InitializeDatabase(this); } public CommerceDBContext():base("CommerceDBConnectionString") { Database.SetInitializer<CommerceDBContext>(new DropCreateDatabaseIfModelChanges<CommerceDBContext>()); } protected override void OnModelCreating(DbModelBuilder modelBuilder) { } public IDbSet<User> Users { get; set; } public IDbSet<Shop> Shops { get; set; } }}
创建ISeller和Seller:
using System.ServiceModel;using WCFModel;namespace WCFService{ [ServiceContract] public interface ISeller { [OperationContract(Name ="AddUser")] bool Add(User user, out int userID); [OperationContract(Name ="AddShop")] bool Add(Shop shop, out int shopID); [OperationContract] [TransactionFlow(TransactionFlowOption.Allowed)] //This means a transaction is allowed to be propagated from the client to this operation bool Add(User user, Shop shop); }}
using System;using System.ServiceModel;using WCFModel;namespace WCFService{ public class Seller : ISeller { [OperationBehavior(TransactionScopeRequired =true,TransactionAutoComplete =true)] public bool Add(User user, Shop shop) { int shopID; int userID; if (Add(user,out userID)) { shop.UserID = userID; return Add(shop, out shopID); } return false; } public bool Add(Shop shop, out int shopID) { using (CommerceDBContext db = new CommerceDBContext()) { try { Shop shopModel = new Shop() { ShopName = shop.ShopName, ShopUrl = shop.ShopUrl, UserID = shop.UserID }; var result=db.Shops.Add(shopModel); db.SaveChanges(); shopID = result.ShopID; return true; } catch (Exception) { shopID = 0; throw; } } } public bool Add(User user, out int userID) { using (CommerceDBContext db = new CommerceDBContext()) { try { User userModel = new User() { UserName = user.UserName, Password = user.Password }; var result = db.Users.Add(userModel); db.SaveChanges(); userID = result.UserID; return true; } catch (Exception) { userID = 0; throw; } } } }}TransactionScopeRequired: 告诉ServiceHost自托管服务,进入我的方法,必须给我加上事务。
TransactionAutoComplete: 方法执行中,如果没有抛出异常,则自动提交。
三、创建WCF宿主WCFHost,并配置app.config
using System;using System.ServiceModel;using WCFService;namespace WCFHost{ class Program { static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(Seller)); host.Open(); Console.WriteLine("wcf 服务已经启动!"); Console.ReadKey(); } }}
<?xml version="1.0" encoding="utf-8"?><configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <system.serviceModel> <services> <service name="WCFService.Seller"> <host> <baseAddresses> <add baseAddress="http://localhost:8733/Design_Time_Addresses/WCFService" /> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="WCFService.ISeller" bindingConfiguration="transactionalWsHttpBinding"> <identity> <dns value="localhost" /> </identity> </endpoint> </service> </services> <bindings> <wsHttpBinding> <binding name="transactionalWsHttpBinding" transactionFlow="true" receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00" /> </wsHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> <entityFramework> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="mssqllocaldb" /> </parameters> </defaultConnectionFactory> </entityFramework> <connectionStrings> <add name="CommerceDBConnectionString" connectionString="Server=LONGXI;Database=Commerce;UId=sa;pwd=!1@2#3qaz;" providerName="System.Data.SqlClient" /> </connectionStrings></configuration>四、创建客户端程序调用wcf服务(用信道生成实例):
using System;using System.ServiceModel;using WCFModel;using WCFService;namespace WCFClient{ class Program { static void Main(string[] args) { var factory = new ChannelFactory<ISeller>(new WSHttpBinding(), new EndpointAddress("http://localhost:8733/Design_Time_Addresses/WCFService")); var client = factory.CreateChannel(); var user = new User { UserName = "zhulongxi1", Password = "1234" }; var shop = new Shop { ShopName = "Shop1", ShopUrl = "http://wwww.shopex.com" }; if(client.Add(user,shop)) Console.WriteLine("插入成功!"); else Console.WriteLine("插入失败!"); Console.ReadKey(); } }}
五、配置Microsoft Distributed Transaction Coordinator(MSDTC)和防火墙
win+r 输入dcomcnfg.exe打开Component Services
打开防火墙的Allow a program or feature through Windows Firewall window,
六、测试:
首先走正常流程(使用事务):
先启动WCFHost:
再运行客户端程序WCFClient:插入成功
然后在Seller类中的Add方法中故意加入异常:
运行客户端程序:
抛出异常了,数据库里面没有新增数据,说明事务起到效果了。(可以把事务去掉,然后再执行,则user 新增了一条,而shop没有新增)
- WCF之分布式事务一
- WCF 分布式事务-应用
- WCF分布式事务
- WCF 分布式事务-应用
- WCF 分布式事务
- WCF 分布式事务的使用
- WCF系列_分布式事务
- WCF分布式事务(EF)
- WCF 使用 WSAtomicTransaction11 分布式事务 Oracle
- WCF系列_分布式事务(上)
- WCF系列_分布式事务(下)
- Spring.Net+WCF实现分布式事务
- WCF系列_分布式事务(上)
- WCF系列_分布式事务(下)
- WCF分布式开发步步为赢(12):WCF事务机制(Transaction)和分布式事务编程
- .net remoting的事务传播以及wcf分布式事务
- 分布式事务解决方案一之:可靠消息最终一致性
- tcc分布式事务源码解析系列(一)之项目结构
- Android taskAffinity属性
- JNI学习(一)hellojni
- 使用WebRTC搭建前端视频聊天室——数据通道篇
- React-Native生命周期详解
- 淘宝商品数据库设计
- WCF之分布式事务一
- 3、scrapy基本概念介绍
- iOS国际化(本地化)详解
- Opencv中的数据类型
- Codeforces 793D Presents in Bankopolis【Dp+记忆化搜索】
- spring boot application properties配置详解
- Java数据结构 HashMap 源码阅读
- 题目1087:约数的个数 九度OJ
- 【Shell】把某一文件夹下所有文件名或者路径存入TXT文档