ORM框架之------Dapper,Net下无敌的ORM
一,介紹:Dapper是一款輕量級ORM工具。如果你在小的項目中,使用Entity Framework、NHibernate 來處理大數據訪問及關系映射,未免有點殺雞用牛刀。你又覺得ORM省時省力,這時Dapper 將是你不二的選擇。
---ORM框架的核心思想是對象關系映射,ORM是將表與表之間的操作,映射成對象和對象之間的操作,就是通過操作實體類來達到操作表的目的。從數據庫提取的數據會自動按你設置的映射要求封裝成特定的對象。之后你就可以通過對對象進行操作來修改數據庫中的數據。這時候你面對的不是信息的碎片,而是一個形象鮮明的對象。
二,假如你喜歡原生的Sql語句,又喜歡ORM的簡單,那你一定會喜歡上Dapper,這款ROMDapper的優勢:
下面介紹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(" ++++");
??????? 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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 递归部门
- 下一篇: jquery ajax示例