FreeSql 是 .NetFramework 4.6+、.NetCore 下的 ORM 功能庫,提供了豐富的功能,支持五種流行數據庫 MySql/SqlServer/PostgreSQL/Oracle/Sqlite。mysql
正常的數據庫都支持跨庫,然而 Sqlite 默認不支持,或者說支持起來較爲麻煩,FreeSql 最關心的是通用、易用性,本文介紹 FreeSql 如何實現 Sqlite 跨庫操做。git
FreeSql 支持並推薦使用 CodeFirst 方式開發項目,這種開發方式很是自由,如同 FreeSql 的命名通常。github
以下定義兩個實體(文章、評論):sql
class Topic { public Guid Id { get; set; } public string Title { get; set; } public string Content { get; set; } public DateTime CreateTime { get; set; } } [Table(Name = "xxxtb.Comment")] class Comment { public Guid Id { get; set; } public Guid TopicId { get; set; } public Topic Topic { get; set; } public string Nickname { get; set; } public string Content { get; set; } public DateTime CreateTime { get; set; } }
咱們但願將 Topic 的數據存到主庫,Comment 的數據存到別外一個庫(xxxtb)。好比使用 mysql,不指定數據庫狀況下,將操做當前數據庫下的表。數據庫
其餘 ado.net 或 ORM 將面臨的問題(默認狀況下):異步
一、驅動只打開了一個庫,或者須要手工調用驅動的方法對其餘庫進行附加;測試
二、項目中可能須要定義多個 orm,實現對多個數據庫的存儲和查詢;優化
三、沒法使用跨庫聯表查詢;ui
使用習慣是 FreeSql 主要攻克的難題,其餘數據庫都行,【吐槽】就你丫的 Sqlite 奇葩,同鏈接下默認作不到跨庫操做(或者說使用不方便)。this
好在現在的 .NET 庫大多數都已經開源,因而翻閱 System.Data.SQLite.Core 源碼作了總結:
SQLiteConnection 鏈接對象在 Open 後,執行以下命令可附加多個數據庫;
attach database [xxxtb.db] as [xxxtb];
因而,
第一步:實現一個擴展方法,使用 OpenAndAttach 代替 Open:
public static void OpenAndAttach(this DbConnection that, string[] attach) { that.Open(); if (attach?.Any() == true) { var sb = new StringBuilder(); foreach(var att in attach) sb.Append($"attach database [{att}] as [{att.Split('.').First()}];\r\n"); var cmd = that.CreateCommand(); cmd.CommandText = sb.ToString(); cmd.ExecuteNonQuery(); } } //異步方法的實現省略...
第二步:增長 ConnectionString 參數 Attachs
Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10
第三步:SqliteConnectionPool 實施
一、解析 Attachs;
var att = Regex.Split(_connectionString, @"Attachs\s*=\s*", RegexOptions.IgnoreCase); if (att.Length == 2) { //此條件說明存在,找到 Attachs 配置的值,而且它支持以逗號分割 var idx = att[1].IndexOf(';'); Attaches = (idx == -1 ? att[1] : att[1].Substring(0, idx)).Split(','); }
二、將原有 Open 方法替換成 OpenAndAttach;
編碼與實施過程完成,接下來測試結果,仍然使用上方給出的兩個實體類型。
static IFreeSql sqlite = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=|DataDirectory|\document.db;Attachs=xxxtb.db;Pooling=true;Max Pool Size=10") .UseAutoSyncStructure(true) .UseLazyLoading(true) .Build(); //秀一波 FreeSql.Repository 擴展包 //安裝方法:dotnet add package FreeSql.Repository var topicRepository = sqlite.GetGuidRepository<Topic>(); var commentRepository = sqlite.GetGuidRepository<Comment>(); //添加測試文章 Guid topicId = FreeUtil.NewMongodbId(); topicRepository.Insert(new Topic { Id = FreeUtil.NewMongodbId(), Title = "文章標題1", Content = "文章內容1", CreateTime = DateTime.Now }); //添加10條測試評論 var comments = Enumerable.Range(0, 10).Select(a => new Comment { Id = FreeUtil.NewMongodbId(), TopicId = topicId, Nickname = $"暱稱{a}", Content = $"評論內容{a}", CreateTime = DateTime.Now }); var affrows = commentRepository.Insert(comments); var find = commentRepository.Select.Where(a => a.Topic.Title == "文章標題1").ToList(); //SELECT a."Id", a."TopicId", a."Nickname", a."Content", a."CreateTime" //FROM "xxxtb"."Comment" a, "Topic" a__Topic //WHERE (a__Topic."Title" = '文章標題1') //find 查詢出了10條數據
而後咱們使用 navicat 附加兩個數據庫查看:
一、FreeUtil.NewMongodbId 是生成有序的 Guid 值,在 FreeSql 中實現,其實可使用 Guid.NewGuid,這裏我認可有秀的嫌疑;
二、文章中的代碼沒有過多的依賴,在 vs2017+.netcore2.2 測試一次運行經過,sqlite 的優點免安裝服務;
三、FreeSql 支持 CodeFirst,即建好實體運行程序,表就會建立;
四、FreeSql.Repository 是擴展包,實現通用 CURD 倉儲層功能,文檔:https://github.com/2881099/FreeSql/wiki/Repository
這個功能其實在 FreeSql 早期就已經實現了,可是一直沒能有時間將過程經驗整理成文章,今天把文章寫完寫全,但願能給你們帶來一點「驚嚇」。FreeSql還有更多細節優化並非路人一眼能看透,若是以爲寫得不錯麻煩點個贊,這也是我繼續寫下去的源動力。
一遍看不明白的話,建議多看幾遍。謝謝觀看!