COM+时代的自动事务
最近看公司的遗留项目代码,调试的时候发现经常报分布式事务错误,可是整个代码里没有看见开启过事务,于是开始研究,发现了这个.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+时代的自动事务的更多相关文章
- 利用AOP实现SqlSugar自动事务
先看一下效果,带接口层的三层架构: BL层: public class StudentBL : IStudentService { private ILogger mLogger; private r ...
- Hibernate自动事务揪出的编码不规范
最近重构的项目(Java初学中),Service层一个获取通知记录报错: org.springframework.dao.InvalidDataAccessResourceUsageException ...
- Aop实现SqlSugar自动事务
http://www.cnblogs.com/jaycewu/p/7733114.html
- 在 ASP.NET Core 中自动启用 CAP 事务
本篇文章旨在描述如何在 ASP.NET Core项目中并以一种简便的方式启用CAP事务,因为在我们的示例中都是直接演示比较直观的方式,没有进行封装,有些初学者同学不太会,找到问我如何封装,本篇文章主要 ...
- sql编程篇 (五) 事务
计算机中的事务 编辑 概念 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用 ...
- CI框架--事务
CI框架中事务封装的很完善,使用起来很简单 1.不开启事务 //不开启事务 前两个sql 能够执行成功,第三个执行失败 $this->device_model->addForCamera( ...
- hibernate(九) 二级缓存和事务级别详讲
序言 这算是hibernate的最后一篇文章了,下一系列会讲解Struts2的东西,然后说完Struts2,在到Spring,然后在写一个SSH如何整合的案例.之后就会在去讲SSM,在之后我自己的个人 ...
- SQLite事务管理
事务管理对数据库一致性是至关重要的.数据库实现ACID属性以确保一致性.SQLite依赖于本地文件锁和页日志来实现ACID属性.SQLite只支持扁平事务,并不支持事务嵌套和保存点能力. 1.1 事务 ...
- SqlServer_事务
事务处理是在数据处理时经常遇到的问题,经常用到的方法有以下三种总结整理如下:方法1:直接写入到sql 中在存储过程中使用 BEGIN TRANS, COMMIT TRANS, ROLLBACK TRA ...
随机推荐
- 1.4isAlive()方法
方法isAlive()的功能是判断当前线程是否处于活动状态 活动状态是线程已经启动且尚未终止,线程处于正在运行或准备开始运行的状态,就认为线程是存活的. 测试如下 package com.cky.th ...
- inline-block 引发的间隙原因与解决方法
这是一个常见的问题,但是一些新人没遇到过可能不会发现,现在我对这种现在进行了分析与总结 设置一些元素为块级元素时一般这么写 li{display:inline-block; *display:inli ...
- 如何将指定文件或文件夹直接提交到svn指定目录
以下步骤适用于客户端是Tortoisesvn 服务端是VisualSVN Server的SVN库: 安装Tortoisesvn 获取配置库路径 checkout想要提交到的SVN库或目录 将需要提交 ...
- VS IDE 中Visual C++ 中的项目属性配置
VS IDE 中Visual C++ 中的项目属性配置 一. Visual C++ 项目系统基于 MSBuild. 虽然可以直接在命令行上编辑 XML 项目文件和属性表,我们仍建议你使用 VS IDE ...
- 如何判断ScrollView滑动方向
1/判断滚动视图左右滚动 { CGFloat startContentOffsetX;//滚动开始的坐标 CGFloat willEndContentOffsetX; //滚动即将停止的坐标 CGFl ...
- XML Publisher 并发程序由于"输出提交处理程序提交失败
http://www.cnblogs.com/benio/archive/2012/03/30/2424900.html xmlp 报表运行完成后,状态为warning,其原因大概有以下3类:1.&q ...
- 如何实现php手机短信验证功能
http://www.qdexun.cn/jsp/news/shownews.do?method=GetqtnewsdetailAction&id=1677 下载php源代码 现在网站在建设网 ...
- python 使用json格式转换
什么是json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programm ...
- dot net core 使用 IPC 进程通信
本文告诉大家如何使用dot net core 和其他进程进行通信 一般都是使用 WCF 或 remoting 做远程通信,但是 dot net core 不支持 WCF 所以暂时我就只能使用 管道通信 ...
- CentOS 7 - 安装Oracle JDK8
我们要在CentOS安装最新版本的JDK8,需要首先将JDK下载到服务器,然后通过操作系统自带的工具yum进行安装. 本文我们将介绍CentOS 7下JDK8的安装. 从官网下载页面找到JDK8的下载 ...