FreeSql 发展到现在,已经有两种稳定的开发模式,以下先简单带过一下。后面才是本文的主题。

方法一:基于 helper 的方式,祼用;

dotnet add package FreeSql

提供 CodeFirst、DbFirst、丰富的表达式树、读写分离、AOP等功能支持;

方法二:基于 Repository + UnitOfWok 的方式;

dotnet add package FreeSql.Repository

这是一个扩展包,提供标准的 IRepository 接口定义与默认实现,以及 UnitOfWork 工作单元的支持,更可怕的是集成了局部/全局过滤器,实现租户、软删除等功能不在话下。

不相信吗?请看以下代码:

public IServiceProvider ConfigureServices(IServiceCollection services) {
services.AddSingleton<IFreeSql>(fsql);
services.AddMvc(); var builder = new ContainerBuilder(); builder.RegisterFreeRepository(filter => filter
.Apply<ISoftDelete>("SoftDelete", a => a.IsDeleted == false)
.Apply<ITenant>("Tenant", a => a.TenantId == 1)
); builder.Populate(services);
var container = builder.Build();
return new AutofacServiceProvider(container);
}

比 abpvnext 还要方便,因为 abp 的相关实体需要实现接口 ISoftDelete、ITenant;

我们没有这个限制,只要过滤器的表达式解析成功,就算可用;

使用在任何实体上的时候,只要 [实体].IsDeleted == false 能解析能过,就算可用;

方式三:基于 DbContext

这个项目仍然是一个扩展包,提类似 EFCore 那样的开发习惯。目前定义的规则如下:

文字规则略显复杂,后边有代码演示,以及图文介绍在 sqlite 和 sqlserver 下的测试过程。

DbContext

  • 提供 SaveChanges 方法;
  • 执行队列;

DbSet

  • 提供 Add、AddRange、Remove、RemoveRange、Update、UpdateRange 方法;
  • 以及 Select 属性(连去原有的 FreeSql 查询对象);
  • 私有对象 states,存储实体的副本哈希集合,key=实体的主键值,value=实体;

Add/AddRange(entitys)

  • 验证 entitys 主键值,是否存在于 states 中,存在时报错;
  • 验证 entitys 主键中存在自增:
    • 若有,则立即开启 DbContext 事务,按数据库种类执行相应的方法,最终将返回的自增值,赋给entitys的属性;
    • 若无,并且 entitys 无主键值,则报错;
    • 否则,进入【打包执行队列】;
  • 完成时更新 states;

Remove/RemoveRange(entitys)

  • 验证 entitys 主键值,若无则报错;
  • 验证 states 中是否存在,若无则提醒应该先查询,再删除;
  • 删除 states 对应的实体;
  • 清除 entitys 内的自增属性值、Guid 类型的值,那这个 entitys 将变为可 Add 状态;
  • 进入【打包执行队列】;

Update/UpdateRange(entitys)

  • 验证 entitys 主键值,若无则报错;
  • 验证 states 中是否存在,若无则提醒应该先查询,再删除;
  • 进入【打包执行队列】;

Select

  • 立即执行队列中的命令(打包方式),以免脏读到未提交的数据;
  • 查询完成时,更新 states 的值;

更新数据规则

  • 对比 states 中存在的历史快照值,返回即将修改的 fields;

演示代码

using FreeSql;

public class SongContext : DbContext {

    public DbSet<Song> Songs { get; set; }
public DbSet<Tag> Tags { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder builder) {
builder.UseFreeSql(这里是IFreeeSql对象);
}
} public class Song {
[Column(IsIdentity = true)]
public int Id { get; set; }
public DateTime? Create_time { get; set; }
public bool? Is_deleted { get; set; }
public string Title { get; set; }
public string Url { get; set; }
}
public class Tag {
[Column(IsIdentity = true)]
public int Id { get; set; }
public string Name { get; set; }
} using (var ctx = new SongContext()) { ctx.Songs.Select.Where(a => a.Id > 10).ToList();
//查询结果,存入 states var song = new Song { };
//可插入的 song ctx.Songs.Add(song);
id = song.Id;
//因有自增类型,立即开启事务执行SQL,返回自增值 var adds = Enumerable.Range(0, 100)
.Select(a => new Song { Create_time = DateTime.Now, Is_deleted = false, Title = "xxxx" + a, Url = "url222" })
.ToList();
//创建一堆无主键值的数据 ctx.Songs.AddRange(adds);
//立即执行,将自增值赋给 adds 所有元素,因为有自增类型,如果其他类型,指定传入主键值,不会立即执行 for (var a = 0; a < adds.Count; a++)
adds[a].Title = "dkdkdkdk" + a; ctx.Songs.UpdateRange(adds);
//批量修改,进入队列 ctx.Songs.RemoveRange(adds.Skip(10).Take(20).ToList());
//批量删除,进入队列,完成时 10-20 元素的主键值会被清除 //ctx.Songs.Update(adds.First()); adds.Last().Url = "skldfjlksdjglkjjcccc";
ctx.Songs.Update(adds.Last());
//单条修改 urls 的值,进入队列 //throw new Exception("回滚"); //ctx.Songs.Select.First();
//这里做一个查询,会立即打包【执行队列】,避免没有提交的数据,影响查询结果 ctx.SaveChanges();
//打包【执行队列】,提交事务
}

在 sqlite 测试

打个岔:为什么一条条的执行?

  • 有自增属性需要获取值;
  • sqlite 没有批量插入获取多个自增的办法,或者您有招来支一支(万分感谢);
  • 后面采用 sqlserver 测试,就不是这个境况了,insert into values(),(),(),然后利用 output 特性返回所有值;
    • 比较蛋疼的是,这个特性不是所有数据库都有

可以看见,最终 SaveChanges 时将不会产生影响的命令,一起打包执行,即采用优化合并的方式进行执行。

例如:

ctx.Songs.Update(adds[0]);
ctx.Songs.Update(adds[1]);

这两个更新操作,会合成一条 SQL 命令执行。

在 sqlserver 测试

其实大致与 sqlite 下相同,唯一的区别在于 AddRange 的处理方式,如图:

当插入单条时,采用了第一行代码的 SQL 命令;

当批量插入时,采用了后面看上去复杂的 SQL 命令;

所有传入的实体属性值在执行完成后,都会更新;

特别说明

FreeSql.DbContext 目前仍处于研究开发阶段,不适合商用;

总结

为什么写这篇文章,时常看见有人说某某 orm 不是真正的 orm,没有 OO 思想。

希望 FreeSql.DbContext 随着时间的积累,稳定性和成熟度有所提升,不久成为一个真正的 ORM。

有人会担心,我们第三方做的不靠谱,没有 EFCore 稳定的说话,这个是当然。

但是我们也有自己的特点,不是吗?我们可以做到多种数据库使用习惯的一致性,这点 EFCore 目前是没有办法解决的难题。

从细节出发,我们的口号是:做 .NETCore 最方便的 ORM!

github: https://github.com/2881099/FreeSql 377星

还请献上宝贵的一星,谢谢观看!!

跟踪测试 DbContext ,向"不是真正的 ORM" 说拜拜的更多相关文章

  1. SQL2008的数据更新跟踪测试 (监控数据表变化,可用于同步)

    POC过程如下: 这里我们建立一个测试环境,模拟数据在 Insert , Update 和 Delete 情况下的跟踪效果.1 .测试脚本的准备,下面脚本建立一个新的数据库环境,并作相应的跟踪配置后向 ...

  2. PHP连接MySQL报错"No such file or directory"的解决办法

    好下面说一下连接MYSQL数据库时报错的解决办法. 1,首先确定是mysql_connect()和mysql_pconnect()的问题,故障现象就是函数返回空,而mysql_error()返回“No ...

  3. Mac下PHP连接MySQL报错"No such file or directory"的解决办法

    首先做个简短的介绍. [说明1]MAC下MYSQL的安装路径: /usr/local/mysql-5.1.63-osx10.6-x86_64 数据库的数据文件在该目录的data文件夹中: 命令文件在b ...

  4. 织梦dedecms自由列表的"不使用目录默认主页"错误修正

    站长用织梦做站时常常发现织梦自由列表有个致命的问题: 即修改"不使用目录默认主页"就永远不会自己勾选啦 打开这个文件 makehtml_freelist_action.php 搜索 ...

  5. SQL Server 更改跟踪(Chang Tracking)监控表数据

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...

  6. Google Dapper-大规模分布式系统的基础跟踪设施

    [说明:本文是阅读Google论文"Dapper, a Large-Scale Distributed Systems Tracing Infrastructure"之后的一个简要 ...

  7. 手机APP测试的几大点

    移动互联网App测试点包括: 1.安全测试: 安全测试包括: a.软件是否存在扣费风险,比如发送短信,拨打电话,连接网络等. b.软件是否存在泄漏用户隐私的风险,比如访问手机信息,访问联系人信息等. ...

  8. APP测试流程

    1 APP测试基本流程 1.1流程图 1.2测试周期 测试周期可按项目的开发周期来确定测试时间,一般测试时间为两三周(即15个工作日),根据项目情况以及版本质量可适当缩短或延长测试时间.正式测试前先向 ...

  9. 移动端app测试

    对于手机项目(应用软件),主要是进行系统测试. 而针对手机应用软件的系统测试,我们通常从如下几个角度开展测试工作: 功能模块测试: 交叉事件测试: 性能测试: 安全测试: 容量测试: 兼容性测试: 接 ...

随机推荐

  1. 在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示

    在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示 当我们在VS的C++中使用vector.list.map等这些STL容器,在开启调试的时 ...

  2. 如何高效的编写与同步博客 (.NET Core 小工具实现)

    一.前言 写博客,可以带给我们很多好处,比如可以让我们结识更多志同道合的人:在写博客过程中去查技术资料或者实践可以让我们对知识的掌握和理解更加深刻:通过博客分享能帮助他人收获分享的快乐等等.写博客真的 ...

  3. Unity3D学习(五):实现一个简单的视觉感知

    前言 在很多第一人称或者第三人称射击游戏的单人模式中,玩家的乐趣往往来源于和各式各样的AI敌人的战斗.而战斗的爆发很多时候是因为这些AI在"看见"玩家后就会立即做出反应,比如开火. ...

  4. MySQL 的性能(下篇)—— 性能优化方法

    简介 文中内容均为阅读前辈的文章所整理而来,参考文章已在最后全指明 本文分为上下两篇: 上篇:MySQL 的 SQL 执行分析 下篇:MySQL 性能优化 下面为下篇内容,分为以下部分: 一.创建表时 ...

  5. Spring中资源的加载ResourceLoader

    http://blog.csdn.net/u011955252/article/details/52912571

  6. 关于Linux虚拟化技术KVM的科普 科普二(KVM虚拟机代码揭秘)

    代码分析文章<KVM虚拟机代码揭秘--QEMU代码结构分析>.<KVM虚拟机代码揭秘--中断虚拟化>.<KVM虚拟机代码揭秘--设备IO虚拟化>.<KVM虚拟 ...

  7. ansj构造最短路径

    一.前言 上节介绍了ansj的原子切分和全切分.切分完成之后,就要构建最短路径,得到分词结果. 以"商品和服务"为例,调用ansj的标准分词: String str = " ...

  8. Oracle .NET Core Beta驱动已出,自己动手写EF Core Oracle

    使用.net core也有一段时间了,一直都没有Oracle官方的正式版驱动程序,更别说EF版本了.之前基于Oracle官方的.net core预览版本写了个Dapper的数据库操作实现,但是总感觉不 ...

  9. 最强AngularJS资源合集

    AngularJS是Google开源的一款JavaScript MVC框架,弥补了HTML在构建应用方面的不足,其通过使用指令(directives)结构来扩展HTML词汇,使开发者可以使用HTML来 ...

  10. 6.app架构基础

    app架构,一个听起来高大尚的名字,很多小伙伴听到这个词语感觉很迷茫,不知道架构具体说的是啥?在q群里,"app后端应该怎么架构"这个问题被问了无数次.通过阅读本文,根据本人提出的 ...