一、事务
1、概念
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
一个事务可以是一条SQL语句,一组SQL语句或整个程序。
2、属性
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
3、类型
(1)手动事务
动事务允许显式处理若干过程,这些过程包括:开始事务、控制事务边界内的每个连接和资源登记、确定事务结果(提交或中止)以及结束事务。尽管此模型提供了对事务的标准控制,但它缺少一些内置于自动事务模型的简化操作。例如,在手动事务中数据存储区之间没有自动登记和协调。此外,与自动事务不同,手动事务中事务不在对象间流动。
如果选择手动控制分布式事务,则必须管理恢复、并发、安全性和完整性。也就是说,必须应用维护与事务处理关联的 ACID 属性所需的所有编程方法。
(2)自动事务
.NET 页、XML Web services方法或 .NET Framework 类一旦被标记为参与事务,它们将自动在事务范围内执行。您可以通过在页、XML Web services 方法或类中设置一个事务属性值来控制对象的事务行为。特性值反过来确定实例化对象的事务性行为。因此,根据声明特性值的不同,对象将自动参与现有事务或正在进行的事务,成为新事务的根或者根本不参与事务。声明事务属性的语法在 .NET Framework 类、.NET 页和 XML Web services 方法中稍有不同。
声明性事务特性指定对象如何参与事务,如何以编程方式被配置。尽管此声明性级别表示事务的逻辑,但它是一个已从物理事务中移除的步骤。物理事务在事务性对象访问数据库或消息队列这样的数据资源时发生。与对象关联的事务自动流向合适的资源管理器,诸如 OLE DB、开放式数据库连接 (ODBC) 或 ActiveX 数据对象 (ADO) 的关联驱动程序在对象的上下文中查找事务,并通过分布式事务处理协调器 (DTC) 在此事务中登记。整个物理事务自动发生。
(3)显式事务
用begin transaction明确指定事务的开始。
(4)隐式事务
打开隐性事务:set implicit_transactions on,当以隐性事务模式操作时,SQL Servler将在提交或回滚事务后自动启动新事务。无法描述事务的开始,只需要提交或回滚事务。
4、事务的commit和Rollback
结束事务包括“成功时提交事务”和“失败时回滚事务”两种情况,在Transact-SQL中可以使用commit和rollback结束事务。
(1)commit
提交事务,用在事务执行成功的情况下,commit保证事务的所有修改都被保存,同时也释放事务中所使用的资源,如事务使用的锁。
(2)rollback
回滚事务,用于事务在执行失败的情况下,将显式事务或隐式事务回滚到事务的起点或事务内的某个保存点。
5、管理事务的语句
开始事务: begin transaction
提交事务:commit transaction
回滚事务: rollback transaction
二、依赖注入
1、依赖注入概念
依赖注入是实现控制反转的一种设计方法,并不是说依赖注入等于控制反转(Inversion of Control,IoC)。控制反转是思想,依赖注入是具体实现方式。
传统模式下是自己建立调用者对象,再去调用其他东西。而依赖注入是实现控制反转的方式,例如通过构造方法注入Service对象,从而建立了调用者(Service对象,相当于上面的斧头),而不是自己手动建立(Service的控制权在容器,而不在于自己)。
传统模式,例如自己new一个Service对象的话,控制器层的实例化肯定比Service层早。但是使用构造函数注入的话,Service层的实例化反而比控制器层早,也就是说Service层构造函数比controller层构造函数先执行。
2、依赖注入的目的
引入依赖注入的目的是为了解耦。说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用。这样做的好处就是如果添加了另一个实现类,不需要修改之前代码,只需要修改注入的地方将实现类替换。上面说的通过接口调用方法,实际上还是需要去实例化接口的实现类,只不过不需要我们手动new 构造实现类,而是交给如微软的DI、Autofac这些工具去构建实现类。我们只需要告诉它们,某个类是某个接口的实现类,当用到的时候,工具(比如,微软的DI)会自动通过构造函数实例化类。
3、常用的依赖注入
.net core自带的DI
Autofac
Ninject
Unity
4、依赖注入的方法
构造函数注入
属性注入
方法注入
目的都是为了实现控制反转。
5、三种生命周期
Transient:服务级别,每次访问Service的时候,就会产生一个新的对象实例。
Scoped: 会话级别(http级别),每次新的http请求时,就会产生一个新的对象实例,同一个http请求,才会复用该相同实例。
Singleton:单例服务,单一实例对象对每个对象和每个请求都是相同的,可以说是不同客户端不同请求都是相同的。
6、为什么要使用依赖注入
减少代码量,代码更加灵活。
忽略内部复杂依赖
管理生命周期
单元测试
方便进行代理(AOP切面编程)