zoukankan      html  css  js  c++  java
  • 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=&quot;Data Source=WUXUELEI\SQLEXPRESS;Initial Catalog=NewData;Integrated Security=True;MultipleActiveResultSets=True&quot;" 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导致的.....

  • 相关阅读:
    Python中property的使用
    超级水王问题
    electrion 修改api.js 就报错
    electron connection lost:The server closed the connection
    electron vscode 调试时始终部分 js 进不了断点
    electron Uncaught TypeError: Cannot read property 'dialog' of undefined
    C# IndexOf 报错 值不能为null,参数名value
    electron-vue 插入 vue-devTools
    Vue调试神器vue-devtools安装
    electrion vue __dirname is a NodeJS variable
  • 原文地址:https://www.cnblogs.com/zhijianliutang/p/2254938.html
Copyright © 2011-2022 走看看