FreeSql 发展到如今,已经有两种稳定的开发模式,如下先简单带过一下。后面才是本文的主题。git
dotnet add package FreeSqlgithub
提供 CodeFirst、DbFirst、丰富的表达式树、读写分离、AOP等功能支持;sql
dotnet add package FreeSql.Repository数据库
这是一个扩展包,提供标准的 IRepository 接口定义与默认实现,以及 UnitOfWork 工做单元的支持,更可怕的是集成了局部/全局过滤器,实现租户、软删除等功能不在话下。ide
不相信吗?请看如下代码:sqlserver
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 能解析能过,就算可用;ui
这个项目仍然是一个扩展包,提相似 EFCore 那样的开发习惯。目前定义的规则以下:url
文字规则略显复杂,后边有代码演示,以及图文介绍在 sqlite 和 sqlserver 下的测试过程。
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(); //打包【执行队列】,提交事务 }
打个岔:为何一条条的执行?
能够看见,最终 SaveChanges 时将不会产生影响的命令,一块儿打包执行,即采用优化合并的方式进行执行。
例如:
ctx.Songs.Update(adds[0]); ctx.Songs.Update(adds[1]);
这两个更新操做,会合成一条 SQL 命令执行。
其实大体与 sqlite 下相同,惟一的区别在于 AddRange 的处理方式,如图:
当插入单条时,采用了第一行代码的 SQL 命令;
当批量插入时,采用了后面看上去复杂的 SQL 命令;
全部传入的实体属性值在执行完成后,都会更新;
FreeSql.DbContext 目前仍处于研究开发阶段,不适合商用;
为何写这篇文章,时常看见有人说某某 orm 不是真正的 orm,没有 OO 思想。
但愿 FreeSql.DbContext 随着时间的积累,稳定性和成熟度有所提高,不久成为一个真正的 ORM。
有人会担忧,咱们第三方作的不靠谱,没有 EFCore 稳定的说话,这个是固然。
可是咱们也有本身的特色,不是吗?咱们能够作到多种数据库使用习惯的一致性,这点 EFCore 目前是没有办法解决的难题。
从细节出发,咱们的口号是:作 .NETCore 最方便的 ORM!
github: https://github.com/2881099/FreeSql 377星
还请献上宝贵的一星,谢谢观看!!