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星
還請獻上寶貴的一星,謝謝觀看!!