update

28810
2020-02-28 07:10:44 +08:00
parent 0d51d58110
commit 6d083642fe
6 changed files with 86 additions and 42 deletions

@@ -48,7 +48,7 @@ FreeSql是一个功能强大的NETStandard库用于对象关系映射程序(O
* [字符串](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e5%ad%97%e7%ac%a6%e4%b8%b2)
* [日期/时间](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e6%97%a5%e6%9c%9f)
* [其他](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0%e5%85%a8%e8%a7%88)
* [自定义函数](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%87%BD%E6%95%B0v01123)
* [自定义函数](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%A3%E6%9E%90)
* [事务](https://github.com/2881099/FreeSql/wiki/%e4%ba%8b%e5%8a%a1)
* [AOP](https://github.com/2881099/FreeSql/wiki/AOP)
* [读写分离](https://github.com/2881099/FreeSql/wiki/%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb)

@@ -126,8 +126,8 @@ UnitOfWork 可将多个仓储放在一个单元管理执行,最终通用 Commi
```csharp
using (var uow = fsql.CreateUnitOfWork()) {
var songRepos = uow.GetRepository<Song>();
var userRepos = uow.GetRepository<User>();
var songRepo = uow.GetRepository<Song>();
var userRepo = uow.GetRepository<User>();
//上面两个仓储由同一UnitOfWork uow 创建
//在此执行仓储操作

@@ -36,7 +36,9 @@
* [字符串](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e5%ad%97%e7%ac%a6%e4%b8%b2)
* [日期/时间](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e6%97%a5%e6%9c%9f)
* [其他](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0%e5%85%a8%e8%a7%88)
* [自定义函数](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%87%BD%E6%95%B0v01123)
* [自定义函数](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%A3%E6%9E%90)
https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%A3%E6%9E%90
* [事务](https://github.com/2881099/FreeSql/wiki/%e4%ba%8b%e5%8a%a1)
* [AOP](https://github.com/2881099/FreeSql/wiki/AOP)
* [读写分离](https://github.com/2881099/FreeSql/wiki/%e8%af%bb%e5%86%99%e5%88%86%e7%a6%bb)

112
事务.md

@@ -1,6 +1,6 @@
FreeSql提供了四种数据库事务的使用方法
FreeSql 提供了四种数据库事务的使用说明
## 外部事务
## 1、外部事务
适合在外部开启事务的场景FreeSql CRUD 提供了 WithTransaction 传入事务对象。
@@ -13,7 +13,7 @@ fsql.Update<xxx>()
ISelect、IInsert、IUpdate、IDelete都支持 WithTransaction 方法。
## 同线程事务
## 2、同线程事务
假设用户购买了价值100元的商品
@@ -26,26 +26,26 @@ ISelect、IInsert、IUpdate、IDelete都支持 WithTransaction 方法。
```csharp
fsql.Transaction(() => {
//fsql.Ado.TransactionCurrentThread 此属性可得到事务对象
//fsql.Ado.TransactionCurrentThread 此属性可得到事务对象
var affrows = fsql.Update<User>().Set(a => a.Wealth - 100)
.Where(a => a.Wealth >= 100)
//判断别让用户余额扣成负数
.ExecuteAffrows();
if (affrows < 1)
throw new Exception("用户余额不足");
//抛出异常,事务退出
var affrows = fsql.Update<User>().Set(a => a.Wealth - 100)
.Where(a => a.Wealth >= 100)
//判断别让用户余额扣成负数
.ExecuteAffrows();
if (affrows < 1)
throw new Exception("用户余额不足");
//抛出异常,事务退出
affrows = fsql.Update<Goods>().Set(a => a.Stock - 1)
.Where(a => a.Stock > 0)
//判断别让用库存扣成负数
.ExecuteAffrows();
if (affrows < 1)
throw new Exception("商品库存不足");
//抛出异常,回滚事务,事务退出
//用户余额的扣除将不生效
affrows = fsql.Update<Goods>().Set(a => a.Stock - 1)
.Where(a => a.Stock > 0)
//判断别让用库存扣成负数
.ExecuteAffrows();
if (affrows < 1)
throw new Exception("商品库存不足");
//抛出异常,回滚事务,事务退出
//用户余额的扣除将不生效
//程序执行在此处,说明都扣成功了,事务完成并提交
//程序执行在此处,说明都扣成功了,事务完成并提交
});
```
@@ -57,38 +57,80 @@ fsql.Transaction(() => {
3、fsql.Transaction 有防止死锁机制60秒事务未结束的将会被其他线程强行提交不是回滚可能造成不完整的事务但仔细一想60秒还没完成的事务是什么原因呢如果嫌60秒太少了可以在重载方法的参数中设置
## UnitOfWork + Repository
## 3、UnitOfWork + Repository
UnitOfWork 可将多个仓储放在一个单元管理执行,最终通用 Commit 执行所有操作,内部采用了数据库事务;
```csharp
using (var uow = fsql.CreateUnitOfWork()) {
var songRepos = uow.GetRepository<Song>();
var userRepos = uow.GetRepository<User>();
var songRepo = uow.GetRepository<Song>();
var userRepo = uow.GetRepository<User>();
//上面两个仓储由同一UnitOfWork uow 创建
//在此执行仓储操作
//这里不受异步方便影响
//上面两个仓储由同一UnitOfWork uow 创建
//在此执行仓储操作
//这里不受异步方便影响
uow.Commit();
uow.Commit();
}
```
## DbContext
参考:在 asp.net core 中注入工作单元方法
```csharp
//第一步:
public class UnitOfWorkRepository<TEntity, TKey> : BaseRepository<TEntity, TKey>
{
public UnitOfWorkRepository(IFreeSql fsql, IUnitOfWork uow) : base(fsql, null, null)
{
this.UnitOfWork = uow;
}
}
public class UnitOfWorkRepository<TEntity> : BaseRepository<TEntity, int>
{
public UnitOfWorkRepository(IFreeSql fsql, IUnitOfWork uow) : base(fsql, null, null)
{
this.UnitOfWork = uow;
}
}
//第二步:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IFreeSql>(fsql);
services.AddScoped<FreeSql.IUnitOfWork>(sp => fsql.CreateUnitOfWork());
services.AddScoped(typeof(IReadOnlyRepository<>), typeof(UnitOfWorkRepository<>));
services.AddScoped(typeof(IBasicRepository<>), typeof(UnitOfWorkRepository<>));
services.AddScoped(typeof(BaseRepository<>), typeof(UnitOfWorkRepository<>));
services.AddScoped(typeof(IReadOnlyRepository<,>), typeof(UnitOfWorkRepository<,>));
services.AddScoped(typeof(IBasicRepository<,>), typeof(UnitOfWorkRepository<,>));
services.AddScoped(typeof(BaseRepository<,>), typeof(UnitOfWorkRepository<,>));
//批量注入程序集内的所有自建仓储类,可以根据自己需要来修改
Assembly[] assemblies = new [] { typeof(XxxRepository).Assembly };
if (assemblies?.Any() == true)
foreach (var asse in assemblies)
foreach (var repo in asse.GetTypes().Where(a => a.IsAbstract == false && typeof(UnitOfWorkRepository).IsAssignableFrom(a)))
services.AddScoped(repo);
}
```
## 4、DbContext
```csharp
using (var ctx = fsql.CreateDbContext()) {
var song = ctx.Set<Song>();
var user = ctx.Set<User>();
//这里不受异步方便影响
var song = ctx.Set<Song>();
var user = ctx.Set<User>();
//这里不受异步方便影响
ctx.SaveChanges();
ctx.SaveChanges();
}
```
## 更新排他锁
## 5、更新排他锁
```csharp
var user = fsql.Select<User>().ForUpdate(true).Where(a => a.Id == 1).ToOne();

@@ -16,8 +16,8 @@ static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
```csharp
using (var uow = fsql.CreateUnitOfWork()) {
var songRepos = uow.GetRepository<Song>();
var userRepos = uow.GetRepository<User>();
var songRepo = uow.GetRepository<Song>();
var userRepo = uow.GetRepository<User>();
//上面两个仓储由同一UnitOfWork uow 创建

@@ -152,7 +152,7 @@
## v0.11.23
- 增加 ExpressionCallAttribute 特性,实现表达式函数自定义解析;[wiki](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%87%BD%E6%95%B0v01123)
- 增加 ExpressionCallAttribute 特性,实现表达式函数自定义解析;[wiki](https://github.com/2881099/FreeSql/wiki/%e8%a1%a8%e8%be%be%e5%bc%8f%e5%87%bd%e6%95%b0#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%A3%E6%9E%90)
- 优化 Contains 表达式解析为 where in 自动拆分,防止大于 1000 的 SQL 错误,如下:
```csharp
var arr = Enumerable.Range(1, 1333).ToArray();