最近很多 .net QQ 群無(wú)故被封停写妥,特別是 wpf 群幾乎全軍覆沒(méi)棘催。依樂(lè)祝的 .net6交流群,曉晨的 .net跨平臺(tái)交流群耳标,導(dǎo)致很多碼友流離失所無(wú)家可歸,借此機(jī)會(huì)使用一次召喚術(shù)邑跪,有需要的請(qǐng)加群:560611514【.NET C#愛(ài)好者】次坡,6406277【C#/.Net Core社區(qū)】,822074314【DotNet開(kāi)發(fā)交流群】
?? 前言
看到標(biāo)題點(diǎn)進(jìn)來(lái)画畅,也許有人問(wèn)砸琅,為什么不用 mysql,為什么不用 sqlite轴踱,為什么不這樣那樣症脂。
其實(shí)有時(shí)候情非得已,被迫使用不由得自己選擇淫僻,沒(méi)有誰(shuí)天天做新項(xiàng)目诱篷,新項(xiàng)目當(dāng)然不會(huì)選 Access 數(shù)據(jù)庫(kù),復(fù)雜的業(yè)務(wù)群體對(duì)方發(fā)送過(guò)來(lái)的文件是 Access 也沒(méi)得選雳灵,難道可以要求對(duì)方公司換數(shù)據(jù)庫(kù)棕所?
Microsoft Office Access是由微軟發(fā)布的關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)。它結(jié)合了 MicrosoftJet Database Engine 和 圖形用戶界面兩項(xiàng)特點(diǎn)悯辙,是 Microsoft Office 的系統(tǒng)程序之一琳省。
Microsoft Office Access是微軟把數(shù)據(jù)庫(kù)引擎的圖形用戶界面和軟件開(kāi)發(fā)工具結(jié)合在一起的一個(gè)數(shù)據(jù)庫(kù)管理系統(tǒng)迎吵。它是微軟OFFICE的一個(gè)成員, 在包括專業(yè)版和更高版本的office版本里面被單獨(dú)出售。2018年9月25日,最新的微軟Office Access 2019在微軟Office 2019里發(fā)布针贬。
MS ACCESS以它自己的格式將數(shù)據(jù)存儲(chǔ)在基于Access Jet的數(shù)據(jù)庫(kù)引擎里击费。它還可以直接導(dǎo)入或者鏈接數(shù)據(jù)(這些數(shù)據(jù)存儲(chǔ)在其他應(yīng)用程序和數(shù)據(jù)庫(kù))。
?? C#.NET 訪問(wèn) Access 數(shù)據(jù)庫(kù)
從 .NETframework 1.0 到現(xiàn)今的 dotnet-7.0桦他,訪問(wèn) Access 數(shù)據(jù)庫(kù)都只能用 oledb 方式蔫巩,微軟歷史訪問(wèn)數(shù)據(jù)庫(kù)的方式有許多種(ado、odbc瞬铸、oledb批幌、ado.net),oledb 是其中的一種嗓节。
連接字符串常見(jiàn)的有兩種:
Provider=Microsoft.Jet.OleDb.4.0;Data Source=d:/accdb/2003.mdb
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=d:/accdb/2007.accdb
Access 支持 SQL 語(yǔ)句荧缘,使用起來(lái)和普通關(guān)系型數(shù)據(jù)庫(kù)差不多,由于不想在代碼中寫(xiě) SQL拦宣,為了讓 crud 操作起來(lái)更加便利截粗,決定引入 C#.NET ORM Freesql,因?yàn)樗С?.NETFramework 4.0 及以后的所有 dotnet 版本鸵隧,適應(yīng)范圍更廣绸罗。
?? FreeSql 介紹
.NET ORM Object Relational Mapping 是一種為了解決面向?qū)ο笈c關(guān)系數(shù)據(jù)庫(kù)存在的互不匹配的現(xiàn)象的技術(shù)。
FreeSql .NET ORM 支持 .NetFramework4.0+豆瘫、.NetCore珊蟀、Xamarin、MAUI外驱、Blazor育灸、以及還有說(shuō)不出來(lái)的運(yùn)行平臺(tái),因?yàn)榇a綠色無(wú)依賴昵宇,支持新平臺(tái)非常簡(jiǎn)單磅崭。目前單元測(cè)試數(shù)量:8500+,Nuget下載數(shù)量:1M+瓦哎。使用最寬松的開(kāi)源協(xié)議 MIT https://github.com/dotnetcore/FreeSql 砸喻,可以商用,文檔齊全蒋譬,甚至拿去賣(mài)錢(qián)也可以割岛。
FreeSql 主要優(yōu)勢(shì)在于易用性上,基本是開(kāi)箱即用犯助,在不同數(shù)據(jù)庫(kù)之間切換兼容性比較好蜂桶,整體的功能特性如下:
- 支持 CodeFirst 對(duì)比結(jié)構(gòu)變化遷移、DbFirst 從數(shù)據(jù)庫(kù)生成實(shí)體類也切;
- 支持 豐富的表達(dá)式函數(shù)扑媚,獨(dú)特的自定義解析腰湾;
- 支持 批量添加、批量更新疆股、BulkCopy费坊、導(dǎo)航屬性,貪婪加載旬痹、延時(shí)加載附井、級(jí)聯(lián)保存、級(jí)聯(lián)刪除两残;
- 支持 讀寫(xiě)分離永毅、分表分庫(kù),租戶設(shè)計(jì)人弓,分布式事務(wù)沼死;
- 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/達(dá)夢(mèng)/神通/人大金倉(cāng)/翰高/Clickhouse/MsAccess Ado.net 實(shí)現(xiàn)包,以及 Odbc 的專門(mén)實(shí)現(xiàn)包崔赌;
8000+個(gè)單元測(cè)試作為基調(diào)意蛀,支持10多數(shù)數(shù)據(jù)庫(kù),我們提供了通用Odbc理論上支持所有數(shù)據(jù)庫(kù)健芭,目前已知有群友使用 FreeSql 操作華為高斯县钥、mycat、tidb 等數(shù)據(jù)庫(kù)慈迈。安裝時(shí)只需要選擇對(duì)應(yīng)的數(shù)據(jù)庫(kù)實(shí)現(xiàn)包:
dotnet add packages FreeSql.Provider.MsAccess
public class DB
{
static Lazy<IFreeSql> accessLazy = new Lazy<IFreeSql>(() => new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.MsAccess, "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=d:/accdb/2007.accdb")
//.UseAutoSyncStructure(true) 自動(dòng)建表若贮,適合新項(xiàng)目
.UseNoneCommandParameter(true)
.UseMonitorCommand(cmd => Trace.WriteLine(cmd.CommandText))
.Build());
public static IFreeSql access => accessLazy.Value;
}
定義 DB.cs 類之后就可以快樂(lè)的 CRUD 了。FreeSql 提供多種 CRUD 使用習(xí)慣痒留,請(qǐng)根據(jù)實(shí)際情況選擇團(tuán)隊(duì)合適的一種:
- 要么 FreeSql兜看,原始用法;
- 要么 FreeSql.Repository狭瞎,倉(cāng)儲(chǔ) + 工作單元習(xí)慣;
- 要么 FreeSql.DbContext搏予,很像 EFCore 的使用習(xí)慣熊锭,兼容 EFCore 99% 的實(shí)體注解;
- 要么 FreeSql.BaseEntity雪侥,充血模式碗殷;
- 要么 直接像 dapper 那樣使用 SqlConnection 擴(kuò)展方法;
? CRUD 模式一:原始用法 API
DB.access.Select<T>(); //查詢
DB.access.Insert<T>(); //插入
DB.access.Update<T>(); //更新
DB.access.Delete<T>(); //刪除
DB.access.InsertOrUpdate<T>()// 插入或更新
DB.access.Transaction(..); //事務(wù)
DB.access.CodeFirst; //CodeFirst 對(duì)象
DB.access.DbFirst; //DbFirst 對(duì)象
DB.access.Ado; //Ado 對(duì)象
DB.access.Aop; //Aop 對(duì)象
DB.access.GlobalFilter; //全局過(guò)濾器對(duì)象
var blogs = DB.access.Select<Blog>()
.Where(b => b.Rating > 3)
.OrderBy(b => b.Url)
.Page(2, 10)
.ToList();
var blog = new Blog { Url = "http://sample.com" };
blog.BlogId = (int)DB.access.Insert(blog).ExecuteIdentity();
DB.access.Update<Blog>()
.Set(b => b.Url, "http://sample2222.com")
.Where(b => b.Url == "http://sample.com")
.ExecuteAffrows();
DB.access.Delete<Blog>()
.Where(b => b.Url == "http://sample.com")
.ExecuteAffrows();
// 等等等速缨。锌妻。級(jí)聯(lián)保存、級(jí)聯(lián)查詢旬牲、導(dǎo)航屬性仿粹。搁吓。。
? CRUD 模式二:倉(cāng)儲(chǔ) + 工作單元
FreeSql.Repository 作為擴(kuò)展吭历,實(shí)現(xiàn)了通用倉(cāng)儲(chǔ)層功能堕仔。與其他規(guī)范標(biāo)準(zhǔn)一樣,倉(cāng)儲(chǔ)層也有相應(yīng)的規(guī)范定義晌区。FreeSql.Repository 參考 abp vnext 接口摩骨,定義和實(shí)現(xiàn)基礎(chǔ)的倉(cāng)儲(chǔ)層(CURD),算比較通用的方法朗若。
- Select/Attach 快照對(duì)象恼五,Update 只更新變化的字段;
- Insert 插入數(shù)據(jù)哭懈,適配各數(shù)據(jù)庫(kù)優(yōu)化執(zhí)行 ExecuteAffrows/ExecuteIdentity/ExecuteInserted灾馒;
- InsertOrUpdate 插入或更新;
- SaveMany 方法快速保存導(dǎo)航對(duì)象(一對(duì)多银伟、多對(duì)多)你虹;
- 工作單元管理事務(wù)
//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IFreeSql>(DB.access);
services.AddScoped<UnitOfWorkManager>();
services.AddFreeRepository(null, typeof(Startup).Assembly);
//批量注入 Service
}
public class SongService
{
readonly IBaseRepository<Song> _repoSong;
readonly IBaseRepository<Detail> _repoDetail;
public SongService(IBaseRepository<Song> repoSong, IBaseRepository<Detail> repoDetail)
{
_repoSong = repoSong;
_repoDetail = repoDetail;
}
[Transactional]
public virtual void Test1()
{
//這里 _repoSong、_repoDetail 所有操作都是一個(gè)工作單元
this.Test2();
}
[Transactional(Propagation = Propagation.Nested)]
public virtual void Test2() //嵌套事務(wù)
{
//這里 _repoSong彤避、_repoDetail 所有操作都是一個(gè)工作單元
}
}
屬性 | 返回值 | 說(shuō)明 |
---|---|---|
EntityType | Type | 倉(cāng)儲(chǔ)正在操作的實(shí)體類型傅物,注意它不一定是 TEntity |
UnitOfWork | IUnitOfWork | 正在使用的工作單元 |
Orm | IFreeSql | 正在使用的 Orm |
DbContextOptions | DbContextOptions | 正在使用的 DbContext 設(shè)置,修改設(shè)置不影響其他 |
DataFilter | IDataFilter<TEntity> | 倉(cāng)儲(chǔ)過(guò)濾器琉预,本對(duì)象內(nèi)生效 |
UpdateDiy | IUpdate<TEntity> | 準(zhǔn)備更新數(shù)據(jù)董饰,與倉(cāng)儲(chǔ)同事務(wù) |
Select | ISelect<TEntity> | 準(zhǔn)備查詢數(shù)據(jù) |
方法 | 返回值 | 參數(shù) | 說(shuō)明 |
---|---|---|---|
AsType | void | Type | 改變倉(cāng)儲(chǔ)正在操作的實(shí)體類型 |
Get | TEntity | TKey | 根據(jù)主鍵,查詢數(shù)據(jù) |
Find | TEntity | TKey | 根據(jù)主鍵圆米,查詢數(shù)據(jù) |
Delete | int | TKey | 根據(jù)主鍵刪除數(shù)據(jù) |
Delete | int | Lambda | 根據(jù) lambda 條件刪除數(shù)據(jù) |
Delete | int | TEntity | 刪除數(shù)據(jù) |
Delete | int | IEnumerable<TEntity> | 批量刪除數(shù)據(jù) |
DeleteCascadeByDatabase | List<object> | Lambda | 根據(jù)導(dǎo)航屬性遞歸數(shù)據(jù)庫(kù)刪除數(shù)據(jù) |
Insert | - | TEntity | 插入數(shù)據(jù)卒暂,若實(shí)體有自增列,插入后的自增值會(huì)填充到實(shí)體中 |
Insert | - | IEnumerable<TEntity> | 批量插入數(shù)據(jù) |
Update | - | TEntity | 更新數(shù)據(jù) |
Update | - | IEnumerable<TEntity> | 批量更新數(shù)據(jù) |
InsertOrUpdate | - | TEntity | 插入或更新數(shù)據(jù) |
FlushState | - | 無(wú) | 清除狀態(tài)管理數(shù)據(jù) |
Attach | - | TEntity | 附加實(shí)體到狀態(tài)管理娄帖,可用于不查詢就更新或刪除 |
Attach | - | IEnumerable<TEntity> | 批量附加實(shí)體到狀態(tài)管理 |
AttachOnlyPrimary | - | TEntity | 只附加實(shí)體的主鍵數(shù)據(jù)到狀態(tài)管理 |
SaveMany | - | TEntity, string | 保存實(shí)體的指定 ManyToMany/OneToMany 導(dǎo)航屬性(完整對(duì)比) |
BeginEdit | - | List<TEntity> | 準(zhǔn)備編輯一個(gè) List 實(shí)體 |
EndEdit | int | 無(wú) | 完成編輯數(shù)據(jù)也祠,進(jìn)行保存動(dòng)作 |
狀態(tài)管理,可實(shí)現(xiàn) Update 只更新變化的字段(不更新所有字段)近速,靈活使用 Attach 和 Update 用起來(lái)非常舒服诈嘿。
? CRUD 模式三:DbContext
FreeSql.DbContext 實(shí)現(xiàn)類似 EFCore 使用習(xí)慣,跟蹤對(duì)象狀態(tài)削葱,最終通過(guò) SaveChanges 方法提交事務(wù)奖亚。
FreeSql 可自動(dòng)識(shí)別 EFCore 實(shí)體特性 Key/Required/NotMapped/MaxLength/StringLength/DatabaseGenerated/Table/Column。
- Select/Attach 快照對(duì)象析砸,Update 只更新變化的字段昔字;
- Add/AddRange 插入數(shù)據(jù),適配各數(shù)據(jù)庫(kù)優(yōu)化執(zhí)行 ExecuteAffrows/ExecuteIdentity/ExecuteInserted首繁;
- AddOrUpdate 插入或更新作郭;
- SaveMany 方法快速保存導(dǎo)航對(duì)象(一對(duì)多陨囊、多對(duì)多);
using (var ctx = DB.oracle.CreateDbContext()) {
//var db1 = ctx.Set<Song>();
//var db2 = ctx.Set<Tag>();
var item = new Song { };
ctx.Add(item);
ctx.SaveChanges();
}
// 或者
public class SongContext : DbContext {
public DbSet<Song> Songs { get; set; }
public DbSet<Tag> Tags { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder builder) {
builder.UseFreeSql(DB.oracle);
}
//每個(gè) DbContext 只觸發(fā)一次
protected override void OnModelCreating(ICodeFirst codefirst)
{
codefirst.Entity<Song>(eb =>
{
eb.ToTable("tb_song");
eb.Ignore(a => a.Field1);
eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired();
eb.Property(a => a.Url).HasMaxLength(100);
}
}
}
提示:FreeSql 兼容 EFCore 99% 的實(shí)體特性
?? CRUD 模式四:BaseEntity
BaseEntity 是一種極簡(jiǎn)單的 CodeFirst 開(kāi)發(fā)方式所坯,特別對(duì)單表或多表CRUD谆扎,利用繼承節(jié)省了每個(gè)實(shí)體類的重復(fù)屬性(創(chuàng)建時(shí)間、ID等字段)芹助,軟件刪除等功能堂湖,進(jìn)行 crud 操作時(shí)不必時(shí)常考慮倉(cāng)儲(chǔ)的使用状土;
dotnet add package FreeSql.Extensions.BaseEntity
public class UserGroup : BaseEntity<UserGroup, int>
{
public string GroupName { get; set; }
}
//添加
var item = new UserGroup { GroupName = "組一" };
item.Insert();
//更新
item.GroupName = "組二";
item.Update();
//添加或更新
item.Save();
//軟刪除
item.Delete();
//恢復(fù)軟刪除
item.Restore();
//根據(jù)主鍵獲取對(duì)象
var item = UserGroup.Find(1);
//查詢數(shù)據(jù)
var items = UserGroup.Where(a => a.Id > 10).ToList();
?? CRUD 模式五:SqlConnection 擴(kuò)展方法(類似 Dapper)
提供了類似 Dapper 的使用方法无蜂,F(xiàn)reeSql 增加了 IDbConnection/IDbTransaction 對(duì)象的擴(kuò)展方法 Select/Insert/Update/Delete 實(shí)現(xiàn) CRUD。
using FreeSql;
using (var conn = new SqlConnection(...))
{
conn.Select<T>().Where(...).ToList();
conn.Insert(new T {}).ExecuteAffrows();
conn.Update().SetSource(new T {}).ExecuteAffrows();
conn.InsertOrUpdate().SetSource(new T {}).ExecuteAffrows();
conn.Delete<T>().Where(...).ExecuteAffrows();
}
- 每個(gè) SqlConnection GetFreeSql() 返回的 IFreeSql 實(shí)例相同蒙谓;
- 可以對(duì) fsql 設(shè)置 Aop 事件送挑,比如監(jiān)視 SQL灰羽;
- IFreeSql 自身的成員 IDbFirst综苔、Transaction 不可用煎饼;
利用本功能可以快速將 FreeSql 使用到項(xiàng)目中,只需要處理好實(shí)體類的特性谤专。
?? 結(jié)束語(yǔ)
作者是什么人躁锡?
作者是一個(gè)入行 18年的老批,他目前寫(xiě)的.net 開(kāi)源項(xiàng)目有:
開(kāi)源項(xiàng)目 | 描述 | 開(kāi)源地址 | 開(kāi)源協(xié)議 |
---|---|---|---|
FreeIM | 聊天系統(tǒng)架構(gòu) | https://github.com/2881099/FreeIM | MIT |
FreeRedis | Redis SDK | https://github.com/2881099/FreeRedis | MIT |
csredis | https://github.com/2881099/csredis | MIT | |
FightLandlord | 斗DI主網(wǎng)絡(luò)版 | https://github.com/2881099/FightLandlord | 學(xué)習(xí)用途 |
FreeScheduler | 定時(shí)任務(wù) | https://github.com/2881099/FreeScheduler | MIT |
IdleBus | 空閑容器 | https://github.com/2881099/IdleBus | MIT |
FreeSql | ORM | https://github.com/dotnetcore/FreeSql | MIT |
FreeSql.Cloud | 分布式tcc/saga | https://github.com/2881099/FreeSql.Cloud | MIT |
FreeSql.AdminLTE | 低代碼后臺(tái)生成 | https://github.com/2881099/FreeSql.AdminLTE | MIT |
FreeSql.DynamicProxy | 動(dòng)態(tài)代理 | https://github.com/2881099/FreeSql.DynamicProxy | 學(xué)習(xí)用途 |
需要的請(qǐng)拿走置侍,這些都是最近幾年的開(kāi)源作品映之,以前更早寫(xiě)的就不發(fā)了。
FreeSql .NET ORM 支持 .NetFramework4.0+蜡坊、.NetCore杠输、Xamarin、MAUI秕衙、Blazor蠢甲、以及還有說(shuō)不出來(lái)的運(yùn)行平臺(tái),因?yàn)榇a綠色無(wú)依賴据忘,支持新平臺(tái)非常簡(jiǎn)單鹦牛。目前單元測(cè)試數(shù)量:8500+,Nuget下載數(shù)量:1M+若河。QQ群:4336577(已滿)、8578575(在線)寞宫、52508226(在線)
- 支持 CodeFirst 模式萧福;
- 支持 DbFirst 模式,支持從數(shù)據(jù)庫(kù)導(dǎo)入實(shí)體類辈赋,或使用實(shí)體類生成工具生成實(shí)體類鲫忍;
- 支持 豐富的表達(dá)式函數(shù)膏燕,以及靈活的自定義解析;
- 支持 導(dǎo)航屬性一對(duì)多悟民、多對(duì)多貪婪加載坝辫,延時(shí)加載,級(jí)聯(lián)保存射亏,級(jí)聯(lián)刪除近忙;
- 支持 讀寫(xiě)分離、分表分庫(kù)智润、過(guò)濾器及舍、樂(lè)觀鎖、悲觀鎖窟绷、分布式事務(wù)锯玛、多租戶(按字段/表/庫(kù));
- 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/達(dá)夢(mèng)/人大金倉(cāng)/神舟通用/南大通用/翰高/華為高斯/ClickHouse/Access 等數(shù)據(jù)庫(kù)兼蜈;
FreeSql 使用最寬松的開(kāi)源協(xié)議 MIT https://github.com/dotnetcore/FreeSql 攘残,可以商用,文檔齊全为狸,甚至拿去賣(mài)錢(qián)也可以歼郭。
8500+個(gè)單元測(cè)試作為基調(diào),支持10多數(shù)數(shù)據(jù)庫(kù)钥平,我們提供了通用Odbc理論上支持所有數(shù)據(jù)庫(kù)实撒,目前已知有群友使用 FreeSql 操作華為高斯、mycat涉瘾、tidb 等數(shù)據(jù)庫(kù)知态。安裝時(shí)只需要選擇對(duì)應(yīng)的數(shù)據(jù)庫(kù)實(shí)現(xiàn)包。
輕量化解釋:了解 FreeRedis立叛、FreeSql负敏、csredis 的人都知道,我們發(fā)布的開(kāi)源項(xiàng)目是綠色著稱秘蛇,零依賴發(fā)布后只有一個(gè)DLL其做,不會(huì)造成使用者項(xiàng)目依賴沖突,支持 .NET 4.0 堪稱屎山項(xiàng)目的救星×藁梗現(xiàn)在還有很多.NET FX4.0 的項(xiàng)目妖泄,這些項(xiàng)目因歷史遺留原因或硬件限制,不能更換 .NET Core 版本艘策。因此這些項(xiàng)目很難使用到現(xiàn)有的開(kāi)源庫(kù)蹈胡,不能使用可靠的開(kāi)源庫(kù),那么很多時(shí)候都要自行實(shí)現(xiàn),在堆積代碼的同時(shí)罚渐,項(xiàng)目也有可能越來(lái)越亂却汉,代碼越來(lái)越渣,項(xiàng)目逐漸變得不穩(wěn)定荷并。