Dapper簡易教程(翻譯自Github上StackExchange/Dapper)

来源:https://www.cnblogs.com/cncc/archive/2018/07/24/9361615.html
-Advertisement-
Play Games

本文源自:https://github.com/cnxy/Dapper-zh-cn 本博客作者與Github上作者(cnxy)實為同一個作者。由於筆者翻譯水平有限,文本中錯誤難免,歡迎指正! 本文翻譯自:StackExchange.Dapper 原版教程源自:Dapper Tutorial 中文教程 ...


本文源自:https://github.com/cnxy/Dapper-zh-cn 

本博客作者與Github上作者(cnxy)實為同一個作者。由於筆者翻譯水平有限,文本中錯誤難免,歡迎指正!

 

本文翻譯自:StackExchange.Dapper

原版教程源自:Dapper Tutorial

中文教程源自:中文Dapper教程.GitBook

中文教程PDF:dapper-tutorial-cn

Dapper - .Net版本的簡單對象映射器

發行說明

請見 stackexchange.github.io/Dapper

組件

Nuget穩定版:

https://www.nuget.org/packages/Dapper

Visual Studio 程式包管理器控制台:

PM> Install-Package Dappe

特點

Dapper是一個NuGet庫,您可以將其添加到項目中,以擴展您的IDbConnection介面。

它提供了3個使用方法:

執行一個查詢並將結果映射到強類型列表

public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

示例:

public class Dog
{
    public int? Age { get; set; }
    public Guid Id { get; set; }
    public string Name { get; set; }
    public float? Weight { get; set; }

    public int IgnoredProperty { get { return 1; } }
}

var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });

Assert.Equal(1,dog.Count());
Assert.Null(dog.First().Age);
Assert.Equal(guid, dog.First().Id);

執行一個查詢並將其映射到動態對象列表

public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

這個方法會執行SQL語句,並返回一個動態列表。

示例:

var rows = connection.Query("select 1 A, 2 B union all select 3, 4");

Assert.Equal(1, (int)rows[0].A);
Assert.Equal(2, (int)rows[0].B);
Assert.Equal(3, (int)rows[1].A);
Assert.Equal(4, (int)rows[1].B);

執行不返回結果的命令

public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)

示例:

var count = connection.Execute(@"
  set nocount on
  create table #t(i int)
  set nocount off
  insert #t
  select @a a union all select @b
  set nocount on
  drop table #t", new {a=1, b=2 });
Assert.Equal(2, count);

多次執行命令

還允許使用相同的參數簽名方便有效地多次執行命令(例如批量載入數據)

示例:

var count = connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
  );
Assert.Equal(3, count); // 插入3行: "1,1", "2,2" 與 "3,3"

這適用於已經實現IEnumerable介面的集合對象T。

性能

Dapper的一個關鍵特性是性能。 以下度量標準顯示了對DB執行500個SELECT語句並將返回的數據映射到對象所需的時間。

性能測試分為3個列表:

  • 支持從資料庫中提取靜態類型對象框架的POCO序列化,使用原生SQL語句。
  • 支持返回動態對象列表框架的動態序列化。
  • 典型的框架用法:通常典型的框架使用與最佳使用性能明顯不同,並且它不會涉及編寫SQL語句。

超過500次迭代的SELECT映射性能 - POCO序列化

方法執行時間備註
手工編碼 (使用 SqlDataReader) 47ms  
Dapper ExecuteMapperQuery 49ms  
ServiceStack.OrmLite (使用Id查詢) 50ms  
PetaPoco 52ms 可以更快
BLToolkit 80ms  
SubSonic CodingHorror 107ms  
NHibernate SQL 104ms  
Linq 2 SQL ExecuteQuery 181ms  
Entity framework ExecuteStoreQuery 631ms  

超過500次迭代的SELECT映射性能 - 動態序列化

方法執行時間備註
Dapper ExecuteMapperQuery (動態) 48ms  
Massive 52ms  
Simple.Data 95ms  

超過500次迭代的SELECT映射性能 - 典型用法

方法執行時間備註
Linq 2 SQL CompiledQuery 81ms 非典型的且不涉及複雜的代碼
NHibernate HQL 118ms  
Linq 2 SQL 559ms  
Entity framework 859ms  
SubSonic ActiveRecord.SingleOrDefault 3619ms  

性能基準測試信息 點擊這裡.

可以任意提交包含其他ORM的補丁 - 運行基準測試時,請確保在Release中編譯,且不能附加調試器 (Ctrl+F5).

或者,你可以使用Frans Bouma的RawDataAccessBencherOrmBenchmark測試套件作為測試工具使用。

參數化查詢

可以匿名類型作為參數進行傳遞,這可以輕鬆地命名這些參數名稱,且能夠在資料庫平臺的查詢分析器中簡單地使用剪切、粘貼SQL語句並運行。

new {A = 1, B = "b"} // A映射到參數@A,B映射到參數@B

列表支持

Dapper允許將IEnumerable<int>作為傳遞參數,並能夠自動地參數化查詢

例子:

connection.Query<int>("select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids", new { Ids = new int[] { 1, 2, 3 } });

以上將被轉換成:

select * from (select 1 as Id union all select 2 union all select 3) as X where Id in (@Ids1, @Ids2, @Ids3)" // @Ids1 = 1 , @Ids2 = 2 , @Ids2 = 3

文字代替

Dapper支持布爾與數字類型的文字代替。

connection.Query("select * from User where UserId = {=Id}", new {Id = 1}));

文字替換不作為參數發送; 更好的計劃和過濾索引用法將被允許,但通常應謹慎在測試後使用。 當註入的值實際上是固定值(例如,特定於查詢的“類別ID”,“狀態代碼”或“區域”)時,此功能特別有用。 當你在思考文字live數據時,也有可能想到also並測試特定於提供程式的查詢提示,如帶有常規參數的OPTIMIZE FOR UNKNOWN

緩衝與未緩衝閱讀器

Dapper的預設行為是執行SQL併在返回時緩衝整個閱讀器。 在大多數情況下,這是理想的,因為它最小化了資料庫中的共用鎖並減少了資料庫網路時間。

但是,在執行大量查詢時,可能需要最小化記憶體占用並僅根據需要載入對象。 為此,將buffered:false傳遞給Query方法。

多重映射

Dapper允許將單個行映射到多個對象。 如果想避免無關的查詢和立即載入關聯,這是一個很關鍵的特性。

例子:

思考這兩個類: Post and User

class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public User Owner { get; set; }
}

class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

現在我們要把posts表單與users表單進行映射查詢。到目前為止,如果我們需要結合2個查詢的結果,我們需要一個新的對象來表達它,但在這種情況下將User對象放在Post對象中更有意義。

這是多重映射的用戶案例。你告訴dapper查詢返回一個Post和一個User對象,然後給它描述你想要對包含PostUser對象的每一行做什麼的函數。 在我們的例子中,我們想要獲取用戶對象並將其放在post對象中。所以編寫函數如下:

(post, user) => { post.Owner = user; return post; }

Query方法的3個類型參數指定dapper應該使用哪些對象及返回的內容進行反序列化行。我們將把這兩行解釋為PostUser的組合,然後我們返回一個Post對象。 因此類型聲明變為

<Post, User, Post>

所有東西都放在一起,看起來像這樣:

var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id";

var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});
var post = data.First();

Assert.Equal("Sams Post1", post.Content);
Assert.Equal(1, post.Id);
Assert.Equal("Sam", post.Owner.Name);
Assert.Equal(99, post.Owner.Id);

Dapper能夠通過假設Id列被命名為“Id”或“id”來拆分返回的行。 如果主鍵不同或者希望將行拆分為“Id”以外的其他位置,請使用可選的splitOn參數。

多重結果

Dapper允許在單個查詢中處理多個結果。

例子:

var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";

using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
   var customer = multi.Read<Customer>().Single();
   var orders = multi.Read<Order>().ToList();
   var returns = multi.Read<Return>().ToList();
   ...
}

存儲過程

Dapper完全支持存儲過程:

var user = cnn.Query<User>("spGetUser", new {Id = 1},
        commandType: CommandType.StoredProcedure).SingleOrDefault();

如果你想要更有趣的東西,你可以這樣做:

var p = new DynamicParameters();
p.Add("@a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

cnn.Execute("spMagicProc", p, commandType: CommandType.StoredProcedure);

int b = p.Get<int>("@b");
int c = p.Get<int>("@c");

Ansi字元串和varchar

Dapper支持varchar參數,如果使用param在varchar列上執行where子句,請確保以這種方式傳遞它:

Query<Thing>("select * from Thing where Name = @Name", new {Name = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = true });

在SQL Server中,使用unicode編碼查詢unicode與ANSI編碼或查詢非unicode編碼時,變得至關重要。

每行類型轉換

通常,自己希望將給定表中的所有行視為相同的數據類型。 但是,在某些情況下,能夠將不同的行解析為不同的數據類型是有用的。 這就是IDataReader.GetRowParser派上用場的地方。

假設有一個名為“Shapes”的資料庫表,其中包含列:IdTypeData,你想要基於Type列的值將它的行解析為CircleSquareTriangle對象。

var shapes = new List<IShape>();
using (var reader = connection.ExecuteReader("select * from Shapes"))
{
    // Generate a row parser for each type you expect.
    // The generic type <IShape> is what the parser will return.
    // The argument (typeof(*)) is the concrete type to parse.
    var circleParser = reader.GetRowParser<IShape>(typeof(Circle));
    var squareParser = reader.GetRowParser<IShape>(typeof(Square));
    var triangleParser = reader.GetRowParser<IShape>(typeof(Triangle));

    var typeColumnIndex = reader.GetOrdinal("Type");

    while (reader.Read())
    {
        IShape shape;
        var type = (ShapeType)reader.GetInt32(typeColumnIndex);
        switch (type)
        {
              case ShapeType.Circle:
                shape = circleParser(reader);
                break;
            case ShapeType.Square:
                shape = squareParser(reader);
                break;
            case ShapeType.Triangle:
                shape = triangleParser(reader);
                break;
              default:
                throw new NotImplementedException();
        }

          shapes.Add(shape);
    }
}

限制與警告

Dapper緩存有關它運行的每個查詢的信息,這使它能夠快速實現對象並快速處理參數。 當前實現將此信息緩存在ConcurrentDictionary對象中。僅使用一次的語句通常會從此緩存中刷新。儘管如此,如果您在不使用參數的情況下動態生成SQL字元串,則可能會遇到記憶體問題。

Dapper的簡潔性意味著ORM附帶的許多功能都被剝離了。Dapper擔心95%的情況,併為您提供大多數時間所需的工具,並不試圖解決所有問題。

Dapper支持哪些資料庫?

Dapper沒有特定於DB的實現細節,它適用於所有.NET ADO提供程式,包括SQLite(https://www.sqlite.org/),SQL CE,Firebird,Oracle,MySQL,PostgreSQL和SQL Server。

有完整的例子清單嗎?

Dapper有一個完整位於測試工程的測試套件。

誰在用這個?

Stack Overflow正在使用Dapper。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 裝飾模式 裝飾模式之前的面向對象原則介紹: 單一職責原則:就一個類而言,應該僅有一個引起它變化的原因。也就是說功能要單一。 優點: 靈活性,可復用性。 如果一個類承擔的職責太多,就等於把這些職責耦合在一起,一個職責的變化可能會削弱或者阻礙其他職責能力,這種耦合會導致脆弱的設計,當變化發生時,設計會發 ...
  • 軟體設計中由一些所謂的理念都沒有一個明確的定義,比如之前流行的SOA和現在炒的火熱的微服務(Micro Service)和無伺服器(Serverless),我們都不能通過一個明確的“內涵”給它們一個準確地定義,只能從“外延”上描述這些架構設計應該具有怎樣的特性。正因為無法給出一個明確的界定,造成了人... ...
  • 文章翻譯集錦 序 在閱讀部分英文文檔的時候,有幾點妨礙因素: 1.伺服器在國外,水土不服; 2.軟體翻譯有時候失敗; 3.載入速度有點慢、有時候不是一般的慢; 4.網站經常打不開; ... ... 系列 IdentityServer4系列(目前已經整理完畢):http://nidie.com.cn/ ...
  • WCF作為.NET Framework3.0就被引入的用於構建面向服務的框架在眾多項目中發揮著重大作用。時至今日,雖然已有更新的技術可以替代它,但對於那些既存項目或產品,使用新框架重構的代價未必能找到人願意買單。 而在.NET Core平臺環境中,WCF也並沒有被完全列入遷移目標。WCF的服務端被擱 ...
  • 據瞭解,目前武漢軟體開發市場關於PC端桌面開發的技術主要有兩塊:winform和wpf。wpf是微軟既winform之後推出的一套新的桌面開發技術。採用數據驅動的方式可以輕鬆編寫出非常炫的界面。 ...
  • /// /// API接收Base64轉圖片 /// /// 圖片位元組 /// 儲存地址 /// public IHttpActionResult Index(String Img, String Path) { //轉圖片 byte[] bit = Convert.FromBase64String... ...
  • 近來,有項目需要使用到 DotNetty 這個非同步Socket框架。 這個框架是 微軟團隊 移植的 Java的 Netty —— 而且還能與 Java 現有的 Netty 對接。 Netty 如何的牛逼 我就不多介紹了。 DotNetty 基於 .Net 4.3 (實際至少需要 .Net 4.... ...
  • 需求:每個平臺分類下的門店,每個門店的名稱、圖片路徑、評分,每個門店下的四個產品的名稱、圖片路徑、評分 思路: 一開始門店動態化好寫,用Ajax就行了。但是每個門店下麵的產品,每個去請求一次查詢有點不太現實。 一開始準備用每個門店的Id去發起請求,被自己蠢哭了。 在換個思路用sql語句吧 同時把這麼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...