DapperPoco -- 基於Dapper的、輕量級的、高性能的、簡單的、靈活的ORM框架


為什么要重復造輪子

因為現有的輪子都在某些方面不太令我滿意,下面我來一一點評一下,歡迎拍磚。

Entity Framework

我喜歡傻瓜化使用方式的框架,同時又不失靈活性。

EF雖然使用起來足夠簡單,但卻不夠靈活。例如,在EF Core中你無法用原生SQL寫一個多表連接查詢(返回的結果是多表連接的結果)

單表簡單條件查詢還好,多表查詢時生成的SQL性能實在不敢恭維,我更喜歡自己寫SQL,可控性更高,心里有底

EF的設計不利於項目的分層;我理想的設計是隔離、低耦合,和數據庫打交道的事就交給Db層好了,所有數據庫的特性都隔離在Db層內部,對外按業務提供傻瓜化的接口。
而使用EF你沒法做到真正的隔離,因為即使能把SaveChanges封裝在Db層,導航屬性也會導致再次查詢數據庫。

Dapper

我喜歡它的輕量級,高性能。但它"只支持"原生SQL讀寫數據庫,使用起來還是不太方便。

很多常用的情景其實可以封裝一下不用寫SQL的,像EF一樣,直接Add一個Entity

雖然現在Dapper已經有了這樣一個封裝,但目前來看實在過於粗糙

PetaPoco

它可以像EF一樣直接Add一個Entity,也可以像Dapper一樣自己寫原生SQL,按理說這已經很完美了。

但是,它不支持批量插入、更新啊

DapperPoco

在實在找不到滿意框架的情況下,於是DapperPoco就誕生了,它是基於Dapper高度封裝的,有Dapper的一切優點,同時也彌補了它的不足,它有如下特點:

  1. 高性能(與Dapper一致),以熱啟動后計算(第一次啟動有緩存過程)
  2. 像EF一樣使用簡單,也可像Dapper一樣靈活使用原生SQL
  3. 支持使用Fluent API定義實體映射
  4. 內部模塊化靈活、可擴展

現已將其開源並放到了github上,地址為:https://github.com/md-frank/DapperPoco

如何使用

首先定義一個Poco類

//表示文章表里的一條記錄
public class Article
{
    public long Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
}

創建DbContext

class MasterDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseConnectionString("連接字符串");
        //使用SQL Server數據庫
        optionsBuilder.UseSqlAdapter(new SqlServerAdapter(SqlClientFactory.Instance));
    }

    //如果不使用Poco可以不重寫此方法
    protected override void OnEntitiesBuilding(EntitiesBuilder entityBuilder)
    {
        //屬性名與表列名(列名)不一樣,可在此映射別名
        entityBuilder.Entity<Article>()
            .TableName("T_Article")
            .ColumnName(p => p.Id, "article_id");
    }
}

插入數據

var masterDb = new MasterDbContext();

//插入一個Poco對象
var a = new Article 
{
    Title = "hello",
    Content = "hello word"
};
masterDb.Insert(a);

//插入了2條記錄
masterDb.Insert(new Article[] { a, a });

//也可以顯式指定表名
masterDb.Insert(a, "T_Article");

//原生SQL插入
this.Execute("insert T_Article(Title, Content) values (@Title, @Content)", a);

//插入了2條記錄
this.Execute("insert T_Article(Title, Content) values (@Title, @Content)", a, a);

//插入了2條記錄
this.Execute("insert T_Article(Title, Content) values (@Title, @Content)", new Article[] { a, a });

//也可以直接寫參數值
this.Execute("insert T_Article(Title, Content) values (@p0, @p1)", "hello", "hello word");

更新數據

var masterDb = new MasterDbContext();

//先查出來准備更新
var article = masterDb.FirstOrDefault<Article>("select * from T_Article where article_id = @p0", 1);

//更新除主鍵外的所有列
article.Title = "hello 2";
article.Content = "content 1";
masterDb.Update(article);

//僅更新指定列,指定表列名
article.Title = "hello 2";
masterDb.Update(article, new [] { "Title" });

//僅更新指定列,指定實體屬性名
article.Title = "hello 3";
article.Content = "content 1";
masterDb.Update(article, null, null, p=> p.Title, p=> p.Content);

保存數據

var masterDb = new MasterDbContext();

var article = new Article 
{
    Id = 1,
    Title = "hello",
    Content = "hello word"
};

//如果記錄存在則更新,不存在則插入
masterDb.Save(article);

//保存並指定列名
masterDb.Save(article, new [] { "Title" });

刪除數據

var masterDb = new MasterDbContext();

var article = masterDb.FirstOrDefault<Article>("select * from T_Article where article_id = @p0", 1);

//刪除實體記錄
masterDb.Delete(article);

//刪除實體記錄,顯式指定主鍵名
masterDb.Delete(article, "article_id");

查詢數據(立即執行)

var masterDb = new MasterDbContext();

//查詢T_Article表所有記錄
var articles = masterDb.FetchAll<Article>();

//指定條件查詢,直接寫參數值
var articles = masterDb.Fetch<Article>("select * from T_Article where Title=@p0 and Content=@p1", "hello", "hello word");

//指定條件查詢,支持列表(實現了IEnumerable接口的)
var articles = masterDb.Fetch<Article>("select * from T_Article where article_id in @p0", new [] { 1, 2, 3 });

//查詢單條記錄
masterDb.FirstOrDefault<Article>("select * from T_Article where article_id = @p0", 1);

//查詢單列
var count = masterDb.ExecuteScalar<long>("select count(*) from T_Article");

//查詢分頁的結果(第1頁,每頁20條)
Paged<Article> paged = masterDb.Paged<Article>(1, 20, "select * from T_Article where Title=@p0", "hello");

//Paged的定義如下
public class Paged<T> where T : new()
{
    //當前頁碼
    public int CurrentPage { get; set; }

    //總頁數
    public int TotalPages { get; set; }

    ///總記錄數
    public long TotalItems { get; set; }

    //每頁記錄數
    public int ItemsPerPage { get; set; }

    //當前頁記錄列表
    public List<T> Items { get; set; }
}

查詢數據(延遲執行)

延遲查詢使用Query,與Fetch不同的是Query返回的結果只有在使用時才會真正查詢數據庫

var masterDb = new MasterDbContext();

//延遲查詢
var articles = masterDb.Query<Article>("select * from T_Article where Title=@p0", "hello");

動態查詢條件

var title = "此變量來自用戶輸入";

var sb = new SqlBuilder();
sb.Append("select * from T_Article");
if(!string.IsNullOrEmpty(title))
    sb.Append("where Title=@p0", title);

var sql = sb.Build();
var articles = masterDb.Fetch<Article>(sql.Statement, sql.Parameters);

事務支持

using (var trans = this.GetTransaction())
{
    //這里修改數據庫

    //提交事務
    trans.Complete();
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM