日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ORM框架之------Dapper,Net下无敌的ORM

發布時間:2025/7/14 编程问答 67 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ORM框架之------Dapper,Net下无敌的ORM 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一,介紹:Dapper是一款輕量級ORM工具。如果你在小的項目中,使用Entity Framework、NHibernate 來處理大數據訪問及關系映射,未免有點殺雞用牛刀。你又覺得ORM省時省力,這時Dapper 將是你不二的選擇。

  ---ORM框架的核心思想是對象關系映射,ORM是將表與表之間的操作,映射成對象和對象之間的操作,就是通過操作實體類來達到操作表的目的。從數據庫提取的數據會自動按你設置的映射要求封裝成特定的對象。之后你就可以通過對對象進行操作來修改數據庫中的數據。這時候你面對的不是信息的碎片,而是一個形象鮮明的對象。

二,假如你喜歡原生的Sql語句,又喜歡ORM的簡單,那你一定會喜歡上Dapper,這款ROMDapper的優勢:

  • 輕量。只有一個文件(SqlMapper.cs),編譯完成之后只有120k(好象是變胖了)
  • 速度快。Dapper的速度接近與IDataReader,取列表的數據超過了DataTable。
  • 支持多種數據庫。Dapper可以在所有Ado.net Providers下工作,包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
  • 可以映射一對一,一對多,多對多等多種關系。
  • 性能高。通過Emit反射IDataReader的序列隊列,來快速的得到和產生對象,性能不錯。
  • 支持FrameWork2.0,3.0,3.5,4.0,4.5  
  • 下面介紹Dapper如何使用,來進行高效開發,以下操作是編譯后在Net3.5下操作的例子,Net4.0下大部分函數有默認值,參數很簡單。

    三, 為什么要擴展Dapper?

    了解Dapper都知道,在書寫代碼時,我們還是會手動寫SQL,擴展的目的就是在完全不改變dapper源代碼和使用基礎上,進行一次封閉,達到零SQL,實現完全對象操作。

    四,原生Dapper使用流程:

      0,兩種下載使用方法:

      (1),推薦下載方法(使用Nuget下載):

      ---Nuget是一個.NET平臺下的開源的項目,它是Visual Studio的擴展。在使用Visual Studio開發基于.NET Framework的應用時,Nuget能把在項目中添加、移除和更新引用的工作變得更加快捷方便。

    ---安裝成功以后,生成一下網站,項目bin目錄下,會生成幾個Dapper文件(主要是Dapper.dll,120k)。

      (2),可以在官網上下載Dapper源代碼,即SqlMapper.cs文件,在項目中App_Code文件夾中加入這個文件,就像Ado.net中的SqlHelper一樣。

      ---源文件地址:https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper%20NET40/SqlMapper.cs

      1,下面可以在項目中開始使用Dapper了

      2,連接數據庫字符串。根據不同的數據庫進行相應設置,如果是SQL,就類似下邊設置;如果是使用SQLite,則設置方法不同。

    private readonly string sqlconnection ="Data Source=RENFB;Initial Catalog=test;User Id=sa;Password=sa;"; //public readonly string mysqlconnectionString =@"server=127.0.0.1;database=test;uid=renfb;pwd=123456;charset='gbk'";

      3,獲取Sql Server的連接數據庫對象。

    public SqlConnection OpenConnection()
    {
    ??? SqlConnection connection = new SqlConnection(sqlconnection);? //這里sqlconnection就是數據庫連接字符串
    ??? connection.Open();
    ??? return connection;
    }
    //獲取MySql的連接數據庫對象。MySqlConnection
    //public MySqlConnection OpenConnection()
    //{
    //???? MySqlConnection connection = new MySqlConnection(mysqlconnectionString);
    //???? connection.Open();
    //???? return connection;
    //}

    注:如果需要換成Mysql數據庫,只用將獲得sql Server的連接數據庫對象的函數注釋掉,取消MySql的連接數據庫對象的函數的注釋,一并取消Mysql連接字符串的注釋,并修改為自己的連接信息。

    Query()方法: Query()是IDbConnection擴展方法并且重載了,從數據庫里提取信息,并用來填充我們的業務對象模型。

      4,//先創建一個類,是數據庫的user表的模型。
      public class user
    ???? {
    ??????? public int id { get; set; }
    ??????? public string name { get; set; }
    ??????? public string address { get; set; }
    ??????? public string age { get; set; }
    ???? }
    5,手寫Sql插入數據(增)

        /// <summary>
    ??????? /// 手寫Sql插入數據
    ??????? /// </summary>
    ??????? public int InsertWithSql()
    ??????? {
    ??????????? using (var conn = SQLiteHelper.OpenConnection())? //這里訪問的是Sqlite數據文件,這里OpenConnection即上邊獲取連接數據庫對象方法
    ??????????? {
    ??????????????? user user=new user();
    ??????????????? user.name = "Dapper01";
    ??????????????? user.address = "周口";
    ??????????????? user.age="15";
    ? //string _sql = "INSERT INTO User(name,address,age)VALUES('Dapper01','周口',13)";
    string _sql = "INSERT INTO User(name,address,age)VALUES(@name,@address,@age)";
    ??????????????? return conn.Execute(_sql,user);
    ??????????? }
    ??????? }

        ---如果不用Dapper,用插入一條數據需要多少代碼量(相對上邊只用了2行代碼,下邊需要用6行代碼):

    ?? public static int insert_news(string title, string content)
    ??? {
    ??????? string sql = "insert into news(title,content,addtime) values(@title,@content,@addtime)";
    ??????? SQLiteParameter[] parameters =
    ??????????? {
    ??????????????? SQLiteHelper.MakeSQLiteParameter("@title", DbType.String, title.Trim()),
    ??????????????? SQLiteHelper.MakeSQLiteParameter("@content", DbType.String, content.Trim()),
    ??????????????? SQLiteHelper.MakeSQLiteParameter("@addtime", DbType.DateTime,DateTime.Now)
    ??????????? };
    ??????? return SQLiteHelper.ExecuteSql(sql, parameters);? //調用SQLiteHelper文件中方法,執行數據庫插入
    ??? }

    6,手寫Sql輸出數據(刪)

    protected void Page_Load(object sender, EventArgs e)
    ??????? {
    ??????????? user user = new user();
    ??????????? user.id = 15;
    ??????????? DeleteColumn(user);
    ??????? }
    //刪除一個類別(3行):
    ??????? public int DeleteColumn(user user)
    ??????? {
    ??????????? using (IDbConnection conn = SQLiteHelper.OpenConnection())
    ??????????? {
    ??????????????? const string query = "delete from user where id=@id";
    ??????????????? return conn.Execute(query, user);
    ??????????? }
    ??????? }

      ---不用Dapper,刪除一條數據,代碼如下(4行):

      public static int del_news(string newid)
    ??? {
    ??????? string sql = "delete from news where newid=@newid";
    ??????? SQLiteParameter[] parameters =
    ??????????? {
    ??????????????? SQLiteHelper.MakeSQLiteParameter("@newid", DbType.String, newid.Trim())
    ??????????? };
    ??????? return SQLiteHelper.ExecuteSql(sql, parameters);
    ??? }

    7,手寫Sql更新數據(改)

    protected void Page_Load(object sender, EventArgs e)
    ??????? {
    ??????????? user user = new user();
    ??????????? user.id = 14;
    ??????????? user.name = "Dapper03";
    ??????????? user.address = "太康";
    ??????????? user.age = "25";
    ??????????? UpdateColumn(user);
    ??????? }

    //更新一個類別:
    ??????? public int UpdateColumn(user user)
    ??????? {
    ??????????? using (IDbConnection conn = SQLiteHelper.OpenConnection())
    ??????????? {
    ??????????????? const string query = "update user set name=@name,address=@address,age=@age where id=@id";
    ??????????????? return conn.Execute(query, user);
    ??????????? }
    ??????? }

    8,手寫Sql查詢數據(查)

    protected void Page_Load(object sender, EventArgs e)
    ??????? {
    ??????????? user user = new user();
    ??????????? user.id = 14;
    ??????????? user=SelectColumn(user.id);
    ??????????? Context.Response.Write(user.name+"|"+user.address+"|"+user.age);
    ??????????? Context.Response.End();
    ??????? }

    //獲取單個user對象。
    ??????? public user SelectColumn(int user_id)
    ??????? {
    ??????????? using (IDbConnection conn = SQLiteHelper.OpenConnection())
    ??????????? {
    ??????????????? const string query = "select * from user where id=@id";
    ??????????????? return conn.Query<user>(query, new {id = user_id}).SingleOrDefault<user>();? //這里用的是linq語法,所以必須引用System.Linq;
    ??????????? }
    ??????? }

      ---這里我們傳遞了一個參數給Query方法,參數可以是任何對象,其屬性在查詢中與sql的參數匹配,由于Query總是返回一個集合,我們只需調用SingleOrDefault方法,因為我們知道總是返回0或1行.

    //獲取user對象的集合。
    ??????? public IEnumerable<user> SelectUsers()
    ??????? {
    ??????????? using (IDbConnection conn = SQLiteHelper.OpenConnection())
    ??????????? {
    ??????????????? const string query = "select * from user order by id asc";
    ??????????????? return conn.Query<user>(query, null);
    ??????????? }
    ??????? }

        protected void Page_Load(object sender, EventArgs e)
    ??????? {
    ??????????? IEnumerable<user> list = SelectUsers();
    ??????????? foreach (var i in list)
    ??????????? {
    ??????????????? Context.Response.Write(i.name + "|" + i.address + "|" + i.age);
    ??????????????? Context.Response.Write("<br/>");
    ??????????? }
    ??????????? Context.Response.End();
    ??????? }

    五,如果想直接插入一個實體對象,Sql語句都不要了,可以在Nuget上下載Dapper的擴展包--->Dapper.SimpleCRUD安裝包。(crud即增查改刪)

    ---使用Dapper.SimpleCRUD時,兩個注意點,1是直接插入實體,類代碼要改:

      public class user
    ??? {
    [Key] //主鍵值前加個key
    ??????? public int id { get; set; }
    ??????? public string name { get; set; }
    ??????? public string address { get; set; }
    ??????? public string age { get; set; }
    ??? }

    ?????? ///<summary>
    ???????? ///實體插入數據
    ???????? ///</summary>
    ??????? public int? InsertWithEntity()
    ??????? {
    ??????????? using (var conn = SQLiteHelper.OpenConnection())
    ??????????? {
    ??????????????? var user = new user { name = "Dapper02", address = "周口",age="22"};
    ??????????????? return conn.Insert(user);
    ??????????? }
    ??????? } 

      ---2是使用sqlite數據庫時,會報錯!錯誤內容如下,因為sqlite不支持scope_identity函數,沒有這個函數:

    SQL logic error or missing database
    no such function: SCOPE_IDENTITY

    5,就是這么簡單,直接在例子中嵌入Sql,很容易擴展為存儲過程,可以使用別名使結果集中的列與業務對象模型(ColumnCat)的屬性對應。

    //下面使用上面的集合顯示出分類。
    List<ColumnCat> AllColumnCat =SelectColumnCats().ToList<ColumnCat>();
    foreach (ColumnCat cat in AllColumnCat.Where(c => c.Parentid == 0))
    {
    ??? Response.Write("Name==>" + cat.Name + "\t");
    ??? Response.Write("時間==>" + cat.ModifiedOn + "\t");
    ??? Response.Write("<br/>");
    ??? foreach (ColumnCat c in AllColumnCat
    ??????????????? .Where<ColumnCat>(subColumnCat => subColumnCat.Parentid == cat.Id))
    ??? {
    ??????? Response.Write("&nbsp;&nbsp;++++");
    ??????? Response.Write("Name==>" + c.Name + "\t");
    ??????? Response.Write("時間==>" + c.ModifiedOn + "\t");
    ??????? Response.Write("<br/>");
    ??? }
    }

    //將一級類別和二級類別顯示在頁面上,如果使用一個遞歸,很容易實現無限級分類(你懂的)。

    7,//Dapper也可以加載填充嵌套對象,考慮這樣一種情形,考慮到新聞的類別屬性,返回類別對象,
    //我們創建一個Column的類
    public class Column
    {
    ??? public int Id { get; set; }
    ??? public string Name { get; set; }
    ??? public DateTime ModifiedDate { get; set; }
    ??? public ColumnCat ColumnCat { get; set; }
    }

    //接下來我們來填充我們的業務對象。
    public IList<Column> SelectColumnsWithColumnCat()
    {
    ??? using (IDbConnection conn = OpenConnection())
    ??? {
    ??????? const string query = "select c.Id,c.Name,c.ModifiedDate,c.ColumnCatid
    ??????? ,cat.id,cat.[Name],cat.ModifiedOn,cat.Parentid from [Column] as c
    ??????? left outer join ColumnCat as cat on c.ColumnCatid=cat.id";
    ??????? return conn.Query<Column, ColumnCat, Column>(query
    ?????????????? , (column, columncat) => { column.ColumnCat = columncat; return column; }
    ?????????????? , null, null, false, "Id", null, null).ToList<Column>();
    ??? }
    }

      注:1,在填充嵌套對象的時候,只好執行 ToList<>方法,否則回報ExecuteReader 要求已打開且可用的連接。連接的當前狀態為已關閉,而單個對象不會報錯,估計是using結束后關閉了連接,而嵌套對象在map的時候又執行了 ExecuteReader,只好在using結束之前返回list集合。 2,嵌套對象的參數是比較多的,主要是前兩個參數,其它參數沒用可以設置為null,不過在4.0版本可以只寫兩個參數,其它參數都有默認值。特別要注意 的是splitOn,這個參數不能為空,否則會報對象為引用的錯誤。【splitOn參數的意思是讀取第二個對象的的分割列,從哪個列起開始讀取第二個對 象,如果表里的自增長列都為Id,可以設置這個參數為”Id”】.

      Execute方法: 正如Query方法是檢索數據的,Execute方法不會檢索數據,它與Query方法非常相似,但它總返回總數(受影響的行數),而不是一個對象集合【如:insert update和delete】.

    8,//接下來向數據庫里添加一個類別
    public int InsertColumnCat(ColumnCat cat)
    {
    ??? using (IDbConnection conn = OpenConnection())
    ??? {
    ??????? const string query = "insert into ColumnCat([name],ModifiedOn,Parentid)
    ??????? values (@name,@ModifiedOn,@Parentid)";
    ??????? int row = conn.Execute(query,cat);
    ??????? //更新對象的Id為數據庫里新增的Id,假如增加之后不需要獲得新增的對象,
    ??????? //只需將對象添加到數據庫里,可以將下面的一行注釋掉。
    ??????? SetIdentity(conn,id=>cat.Id=id,"id","ColumnCat");???
    ??????? return row;
    ??? }
    }
    public void SetIdentity(IDbConnection conn, Action<int> setId,string primarykey
    ????????????????????????? ,string tableName)
    {
    ??? if (string.IsNullOrEmpty(primarykey)) primarykey = "id";
    ??? if (string.IsNullOrEmpty(tableName))
    ??? {
    ??????? throw new ArgumentException("tableName參數不能為空,為查詢的表名");
    ??? }
    ??? string query = string.Format("SELECT max({0}) as Id FROM {1}", primarykey
    ???????????????????????? , tableName);
    ??? NewId identity = conn.Query<NewId>(query, null).Single<NewId>();
    ??? setId(identity.Id);
    }
    public class NewId
    {
    ??? public int Id { get; set; }
    }

      由于Dapper是通過類的屬性自動綁定的,所以增 加了NewId類來獲取增加對象后的Id,本來打算使用@@identity,Net3.5下使用總是報錯,只好使用Max函數獲取。當然如果不需要獲得 更新后的對象的ID,可以不使用SetIdentity,這個函數通用。

    編譯Dapper源碼生成的是Net4.0下使用的,可以借助Net4.0新增的dynamic動態類型,
    //SetIdentity的實現將非常方便。如下:
    public void SetIdentity<T>(IDbConnection conn, Action<int> setId)
    {
    ??? dynamic identity = connection.Query("SELECT @@IDENTITY AS Id").Single();
    ??? T newId = (T)identity.Id;
    ??? setId(newId);
    }
    9,下面介紹一下Dapper的高級用法
    //Dapper對事務處理的例子,如刪除類別的同時刪除類別下的所有新聞。或者刪除產品的同時,
    //刪除產品圖片表里關聯的所有圖片。
    public int DeleteColumnCatAndColumn(ColumnCat cat)
    {
    ??? using (IDbConnection conn = OpenConnection())
    ??? {
    ??????? const string deleteColumn = "delete from [Column] where ColumnCatid=@catid";
    ??????? const string deleteColumnCat = "delete from ColumnCat where id=@Id";
    ??????? IDbTransaction transaction = conn.BeginTransaction();
    ??????? int row=conn.Execute(deleteColumn, new { catid =cat.Id},transaction,null,null);
    ??????? row += conn.Execute(deleteColumnCat, new { id=cat.Id},transaction,null,null);
    ??????? transaction.Commit();
    ??????? return row;
    ??? }
    }

    轉載于:https://www.cnblogs.com/lihuali/p/7792184.html

    總結

    以上是生活随笔為你收集整理的ORM框架之------Dapper,Net下无敌的ORM的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。