最近看公司的遗留项目代码,调试的时候发现经常报分布式事务错误,可是整个代码里没有看见开启过事务,于是开始研究,发现了这个.Net Framework1.1时代的产物。

namespace BusinessService
{
    [Transaction(TransactionOption.RequiresNew, Isolation = TransactionIsolationLevel.ReadCommitted)]
    public class Operation : ServicedComponent, IOperation
        //public class Operation : MarshalByRefObject, IOperation
    {
        private static List<Person> persons = new List<Person>();
        private static string dbStr = "Data Source=DESKTOP-PABLR9F;Initial Catalog=MyDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
        public Operation()
        {
            Console.WriteLine("服务激活...");
        }
        public int AddPerson(Person person)
        {
            Console.WriteLine("添加Person...");
            var s = persons.FirstOrDefault(x => x.Id == person.Id);
            if(s==null)
            {
                persons.Add(person);
                ;
            }
            else
            {
                ;
            }
        }
        [AutoComplete(true)]
        public void AddPersons()
        {
            List<Person> list = new List<Person>();
            ; i <= ; i++)
            {
                Person p =  + i };
                list.Add(p);
            }
            using (SqlConnection conn = new SqlConnection(dbStr))
            {
                if (conn.State != System.Data.ConnectionState.Open)
                    conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    foreach (var item in list)
                    {
                        string sql = string.Format("insert into student(name,age,lasttime) values( '{0}',{1},'{2}')",item.Name,item.Age,DateTime.Now);
                        cmd.CommandText = sql;
                        cmd.ExecuteNonQuery();
                    }
                }
            }

        }
        [AutoComplete(true)]
        public void AddPersonRange(ArrayList list)
        {
            using (SqlConnection conn = new SqlConnection(dbStr))
            {
                if (conn.State != System.Data.ConnectionState.Open)
                    conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    foreach (Person item in list)
                    {
                        string sql = string.Format("insert into student(name,age,lasttime) values( '{0}',{1},'{2}')", item.Name, item.Age, DateTime.Now);
                        cmd.CommandText = sql;
                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }

        public Person GetPerson(int id)
        {
            Console.WriteLine("获取Person...");
            return persons.FirstOrDefault(x => x.Id == id);
        }

        public DateTime GetTime()
        {
            Console.WriteLine("获取时间:"+DateTime.Now);
            return DateTime.Now;
        }
    }
}

让类继承ServicedComponent,这样调用类的方法的时候会自动开启事务

然后在方法上加上[AutoComplete(true)]属性,这样在方法结束的时候会自动结束事务

这个项目是用remoting做的,顺便把这个也看了看

整体框架:

接口层:

namespace BusinessContract
{
    [Serializable]
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime LastTime { get; set; }
    }
}

服务层:

namespace BusinessService
{
    [Transaction(TransactionOption.RequiresNew, Isolation = TransactionIsolationLevel.ReadCommitted)]
    public class Operation : ServicedComponent, IOperation
        //public class Operation : MarshalByRefObject, IOperation
    {
        private static List<Person> persons = new List<Person>();
        private static string dbStr = "Data Source=DESKTOP-PABLR9F;Initial Catalog=MyDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";
        public Operation()
        {
            Console.WriteLine("服务激活...");
        }
        public int AddPerson(Person person)
        {
            Console.WriteLine("添加Person...");
            var s = persons.FirstOrDefault(x => x.Id == person.Id);
            if(s==null)
            {
                persons.Add(person);
                ;
            }
            else
            {
                ;
            }
        }
        [AutoComplete(true)]
        public void AddPersons()
        {
            List<Person> list = new List<Person>();
            ; i <= ; i++)
            {
                Person p =  + i };
                list.Add(p);
            }
            using (SqlConnection conn = new SqlConnection(dbStr))
            {
                if (conn.State != System.Data.ConnectionState.Open)
                    conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    foreach (var item in list)
                    {
                        string sql = string.Format("insert into student(name,age,lasttime) values( '{0}',{1},'{2}')",item.Name,item.Age,DateTime.Now);
                        cmd.CommandText = sql;
                        cmd.ExecuteNonQuery();
                    }
                }
            }

        }
        [AutoComplete(true)]
        public void AddPersonRange(ArrayList list)
        {
            using (SqlConnection conn = new SqlConnection(dbStr))
            {
                if (conn.State != System.Data.ConnectionState.Open)
                    conn.Open();
                using (SqlCommand cmd = conn.CreateCommand())
                {
                    foreach (Person item in list)
                    {
                        string sql = string.Format("insert into student(name,age,lasttime) values( '{0}',{1},'{2}')", item.Name, item.Age, DateTime.Now);
                        cmd.CommandText = sql;
                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }

        public Person GetPerson(int id)
        {
            Console.WriteLine("获取Person...");
            return persons.FirstOrDefault(x => x.Id == id);
        }

        public DateTime GetTime()
        {
            Console.WriteLine("获取时间:"+DateTime.Now);
            return DateTime.Now;
        }
    }
}

服务端:

static void Main(string[] args)
        {
            //IClientChannelSinkProvider clientProvider = new BinaryClientFormatterSinkProvider();
            //IServerChannelSinkProvider serverProvider = new BinaryServerFormatterSinkProvider();
            //IDictionary dict = new Hashtable();
            //dict["port"] = 8080;
            //dict["name"] = "myServer";
            //HttpChannel channel = new HttpChannel(dict, clientProvider, serverProvider);

            //int port = Convert.ToInt32(ConfigurationManager.AppSettings["port"].ToString());
            //HttpChannel channel = new HttpChannel(port);
            //ChannelServices.RegisterChannel(channel, false);
            //RemotingConfiguration.RegisterWellKnownServiceType(typeof(Operation), "ServiceOperation", WellKnownObjectMode.SingleCall);
            RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
            Console.WriteLine("服务端启动...");
            Console.ReadKey();
        }

服务端配置:

<system.runtime.remoting>
    <!--.net remoting配置的根节点-->
    <application>
      <!--包含有关远程应用程序使用及公共的对象信息-->
      <service>
        <!--服务器端,用于指定以什么方式公开什么对象-->
        <wellknown mode="Singleton" type="BusinessService.Operation,BusinessService" objectUri="ServiceOperation"/>
        <!--与wellknown相对是activated,wellknown表示服务器端激活对象,后者为客户端激活对象-->
        <!--mode表示如何响应客户端请求,Singleton表示单一实例-->
        <!--type表示要公开的类型,选择指定类型名称(含名称空间),然后指定类型所属.dll文件-->
        <!--objectUri表示远程对象访问路径-->
      </service>
      <channels>
        <!--用于指定通道信息,可心同时指定多个通道-->
        <channel port=" ref="http">
          <clientProviders>
            <formatter ref="binary" />
          </clientProviders>
        </channel>
        <!--具体的通道信息,port为端口号,ref为引用的通道类型-->
        <!--.net 框架提供了http与tcp通道-->

      </channels>
    </application>
  </system.runtime.remoting>

客户端:

static void Main(string[] args)
        {
            //HttpChannel channel = new HttpChannel();
            //ChannelServices.RegisterChannel(channel, false);
            RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, false);
            string serverUrl = ConfigurationManager.AppSettings["serverUrl"].ToString();

            IOperation op = (IOperation)Activator.GetObject(typeof(IOperation), serverUrl);
            Console.WriteLine(op.GetTime());
            //Console.ReadLine();
            Person person = , Name =  };
            op.AddPerson(person);
            Person p = op.GetPerson();
            Console.WriteLine(p.Name + ":" + p.Age);
            List<Person> list = new List<Person>();
            ArrayList al = new ArrayList();
            ;i<=;i++)
            {
                Person p1 =  + i };
                list.Add(p1);
                al.Add(p1);
            }
            op.AddPersons();
            op.AddPersonRange(al);
            Console.WriteLine("Done");
            Console.ReadKey();
        }

客户端配置:

<system.runtime.remoting>
    <application>
      <client>
        <wellknown url="http://10.200.80.172:8080/ServiceOperation" type="BusinessContract.IOperation,BusinessContract"/>
      </client>
      <!--远程对象访问路径,域名与IP地址都可以-->
      <channels>
        <channel ref="http"/>
        <!--port为0表示客户端不侦听任何端口-->
        <clientProviders>
          <formatter ref="binary" />
        </clientProviders>
        <serverProviders>
          <formatter ref="binary" />
        </serverProviders>
      </channels>
    </application>
  </system.runtime.remoting>

要注意的是:需要把程序集设置为[assembly: ComVisible(true)]

还需要对程序集进行签名:

COM+时代的自动事务的更多相关文章

  1. 利用AOP实现SqlSugar自动事务

    先看一下效果,带接口层的三层架构: BL层: public class StudentBL : IStudentService { private ILogger mLogger; private r ...

  2. Hibernate自动事务揪出的编码不规范

    最近重构的项目(Java初学中),Service层一个获取通知记录报错: org.springframework.dao.InvalidDataAccessResourceUsageException ...

  3. Aop实现SqlSugar自动事务

    http://www.cnblogs.com/jaycewu/p/7733114.html

  4. 在 ASP.NET Core 中自动启用 CAP 事务

    本篇文章旨在描述如何在 ASP.NET Core项目中并以一种简便的方式启用CAP事务,因为在我们的示例中都是直接演示比较直观的方式,没有进行封装,有些初学者同学不太会,找到问我如何封装,本篇文章主要 ...

  5. sql编程篇 (五) 事务

    计算机中的事务 编辑 概念 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用 ...

  6. CI框架--事务

    CI框架中事务封装的很完善,使用起来很简单 1.不开启事务 //不开启事务 前两个sql 能够执行成功,第三个执行失败 $this->device_model->addForCamera( ...

  7. hibernate(九) 二级缓存和事务级别详讲

    序言 这算是hibernate的最后一篇文章了,下一系列会讲解Struts2的东西,然后说完Struts2,在到Spring,然后在写一个SSH如何整合的案例.之后就会在去讲SSM,在之后我自己的个人 ...

  8. SQLite事务管理

    事务管理对数据库一致性是至关重要的.数据库实现ACID属性以确保一致性.SQLite依赖于本地文件锁和页日志来实现ACID属性.SQLite只支持扁平事务,并不支持事务嵌套和保存点能力. 1.1 事务 ...

  9. SqlServer_事务

    事务处理是在数据处理时经常遇到的问题,经常用到的方法有以下三种总结整理如下:方法1:直接写入到sql 中在存储过程中使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRA ...

随机推荐

  1. cyclone IV中DDR的一个报错{Too many output and bidirectional pins per VCCIO and ground pair in I/O bank 8 }

    Error (169224): Too many output and bidirectional pins per VCCIO and ground pair in I/O bank 8 when ...

  2. (转)可伸缩性最佳实践:来自eBay的经验

    转自:http://www.infoq.com/cn/articles/ebay-scalability-best-practices 在eBay,可伸缩性是我们每天奋力抵抗的一大架构压力.我们所做的 ...

  3. mach_absolute_time 使用

    今天看荣哥时间常用函数封装里有个不常见的函数 ,mach_absolute_time() ,经查询后感觉是个不错的函数,网上关于这个函数搜索以后简单整理来一下. 什么事Mach? 时间例程依赖于所需要 ...

  4. Alpha阶段敏捷冲刺(八)

    1.站立式会议 提供当天站立式会议照片一张 2.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 祁泽文:写了关于统计的按钮的代码. 徐璐琳:完善了&q ...

  5. noip第2课作业

    1.    大象喝水 [问题描述] 一只大象口渴了,要喝20升水才能解渴,但现在只有一个深h厘米,底面半径为r厘米的小圆桶(h和r都是整数).问大象至少要喝多少桶水才会解渴. 输入:输入有一行,包行两 ...

  6. POJ1274 The Perfect Stall

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25739   Accepted: 114 ...

  7. 第88讲:Scala中使用For表达式实现map、flatMap、filter

    今天我们来学习一下如何使用for表达式实现map.flatMap以及filter 首先,我们来看下map.map的功能是,传入一个list,通过一个函数f,将list中的元素A变成元素B的过程.最后得 ...

  8. unigui web app之title buttons

    unigui web app之title buttons title buttons:窗体标题按钮 通过 窗体标题按钮,可以方便地导航,比如返回主页. 处理窗体标题按钮的点击事件: procedure ...

  9. [杂谈] 一个关于 as 的小测试

    代码如下:   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 procedure TForm1.Button1Click(Sender: TObject); va ...

  10. [Proposal]Nano-Diary(纳日记)

    [Motivation] 很多人都有记日记的习惯,不为别的,就为了那份情怀.但是也有很多人不记日记,原因是嫌写字麻烦.记得很久很久以前,在<读者>上读过一篇文章,大意是一个人用数值记下每天 ...