我們都知道,ORM全稱是,Object Relationship Mapper,即,對象關係映射。也就是可以用object來map我們的db,而且市面上的orm框架有很多,其中有一個框架叫做dapper,而且被稱為the king of ORM。 市場上,也有一些其他的ORM,比如EF Core,N ...
我們都知道,ORM全稱是,Object Relationship Mapper,即,對象關係映射。也就是可以用object來map我們的db,而且市面上的orm框架有很多,其中有一個框架叫做dapper,而且被稱為the king of ORM。
市場上,也有一些其他的ORM,比如EF Core,NHibernate 、FreeSQL等等,來處理大數據訪問及關係映射。既然官方推出了EF Core,說明其對框架的支持會很友好,為什麼又會有那麼多的ORM框架供我們使用呢?其實,每一個框架都有其適用的場景。如果你在小的項目中,使用Entity Framework、Entity Framework Core、NHibernate 來處理大數據訪問及關係映射,未免有點殺雞用牛刀。你又覺得ORM省時省力,這時Dapper 將是你不二的選擇。其實,Entity Framework Core的性能並不是很高,當對性能有要求的時候,一般公司都會自己封裝一套ORM。
為什麼選擇Dapper?
- 輕量。只有一個文件(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
在這裡,我們在dotnet core下麵使用Dapper操作MySQL。
首先,既然是演示,就先創建一個core MVC的項目,這裡選擇有模板的。因為公司使用的是dotnet core2.2的版本,我就基於core2.2版本創建一個項目。
Dapper安裝,使用NuGet來安裝Dapper程式包
使用NuGet安裝MySQL.Data的程式包
安裝這些程式包之後,在appsettings.json文件中添加鏈接資料庫的字元串:
"ConnectionStrings": {
"DefaultConnection": "server=伺服器;port=埠號;database=regatta{0};SslMode=None;uid=userName;pwd=passWord;Allow User Variables=true"
}
然後,封裝一個工具類,來獲得我們的連接字元串,和管理連接池。
public class BaseRepository : IDisposable { public static IConfigurationRoot Configuration { get; set; } public static MySqlConnection conn; public static MySqlConnection GetMySqlConnection(bool open = true, bool convertZeroDatetime = false, bool allowZeroDatetime = false) { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); var cs = builder.GetSection("ConnectionStrings:DefaultConnection").Value; var csb = new MySqlConnectionStringBuilder(cs) { AllowZeroDateTime = allowZeroDatetime, ConvertZeroDateTime = convertZeroDatetime }; conn = new MySqlConnection(csb.ConnectionString); return conn; } public void Dispose() { if (conn != null && conn.State != System.Data.ConnectionState.Closed) { conn.Close(); } } }
或者, 在startup中註冊dapper倉儲,並現時註冊資料庫類型和資料庫連接串,因為在mysql和sqlserver中,它們的連接串是不同的,模塊化設計請看大叔這篇文章,《DotNetCore跨平臺~組件化時代來了》
services.UseLog4Logger(o => { o.Log4ConfigFileName = "log4.config"; o.ProjectName = "test"; }).UseDapper(o => { o.ConnString = "server=伺服器;port=埠號;database=regatta{0};SslMode=None;uid=userName;pwd=passWord;Allow User Variables=true"; o.DbType = DbType.MySql; }).UseDefaultMQ();
創建資料庫中的一個需要映射的實體類:
public class Area { public int ID { get; set; } public string Name { get; set; } public int ParentID { get; set; } }
當有些時候,資料庫中的表名,與我們定義的實體類的類名,可能會不一致。這個時候,就需要加一個特性標簽來聲明瞭:
[Display(Name = "tbl_area")] public class Area { public int ID { get; set; } public string Name { get; set; } public int ParentID { get; set; } }
當然,有些表中的欄位與實體類中的自己定義的屬性,也不一樣,其實有好多解決方法,可以在使用T-SQL的時候,使用別名。比如,SELECT id AS ID FROM TABLE..,或者使用特性標簽,具體請參考:https://www.cnblogs.com/efreer/p/8277329.html
查詢操作
/// <summary> /// 查詢單個數據 /// </summary> /// <param name="Id"></param> /// <returns></returns> public static Area QueryFirstOrDefault(int Id) { var sql = "SELECT * from Area where id =@ID"; using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.QueryFirstOrDefault<Area>(sql, new { ID = Id }); } }
/// <summary> /// 查詢所有數據 /// </summary> /// <returns></returns> public static List<Area> QueryList() { var sql = "select * from Area"; using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.Query<Area>(sql).ToList(); } }
/// <summary> /// In操作 /// </summary> public static List<Area> QueryIn() { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { var sql = "select * from Area where id in @ids"; //參數類型是Array的時候,dappper會自動將其轉化 return connection.Query<Area>(sql, new { ids = new int[2] { 1, 2 }, }).ToList(); } } public static List<Area> QueryIn(int[] ids) { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { var sql = "select * from Area where id in @ids"; //參數類型是Array的時候,dappper會自動將其轉化 return connection.Query<Area>(sql, new { ids }).ToList(); } }
插入操作
/// <summary> /// 插入一條數據 /// </summary> /// <param name="Area"></param> /// <returns></returns> public static int Insert(Area Area) { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.Execute($"INSERT INTO Area(Name,ParentID) VALUES(@Name,@ParentID)", Area); } } /// <summary> /// 批量插入Area數據,返回影響行數 /// </summary> /// <param name="Areas"></param> /// <returns></returns> public static int Insert(List<Area> Areas) { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.Execute("INSERT INTO Area(ID,Name,ParentID) VALUES(@ID,@Name,@ParentID)", Areas); } }
刪除操作
/// <summary> /// 刪除一條 /// </summary> /// <param name="Area"></param> /// <returns></returns> public static int Delete(Area Area) { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.Execute("DELETE FROM Area WHERE id=@ID", Area); } } /// <summary> /// 批量刪除 /// </summary> /// <param name="Areas"></param> /// <returns></returns> public static int Delete(List<Area> Areas) { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.Execute("DELETE FROM Area WHERE id=@ID", Areas); } }
修改操作
/// <summary> /// 修改 /// </summary> /// <param name="Area"></param> /// <returns></returns> public static int Update(Area Area) { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.Execute("update Area set name=@name where id=@ID", Area); } } /// <summary> /// 批量修改 /// </summary> /// <param name="Areas"></param> /// <returns></returns> public static int Update(List<Area> Areas) { using (IDbConnection connection = BaseRepository.GetMySqlConnection()) { return connection.Execute("update Area set name=@name where id=@ID", Areas); } }
Join操作
我們是面向對象編程,所以一個對象裡面會有許多其他子對象,這個子對象裡面又有其自己的子對象,這種關係在資料庫里的表示就是外鍵。
比如我們有一本書book,它有主人person,book是一個對象,主人又是一個對象。
public class BookWithPerson { public int ID { get; set; } public Person Pers { get; set; } public string BookName { get; set; } }
我們自然想要一個方法把資料庫里複雜的外鍵關係轉成我們需要的對象BookWithArea,所有我們需要的信息都存在裡面,取數據的時候只要找這個對象取數據就行了,比如我們需要一本書的主人的姓名,我們只需要bookWithArea.Pers.Name。如果是一對多的關係我們用數組,如果是多對多我們加一層mapping。
現在我們想根據書的ID查詢書的信息,包括主人信息。那麼
public static BookWithPerson QueryJoin(Book book) { using (IDbConnection connection = new SqlConnection(connectionString)) { var sql = @"select b.id,b.bookName,p.id,p.name,p.remark from Person as p join Book as b on p.id = b.personId where b.id = @id;"; var result = connection.Query<BookWithPerson, Person, BookWithPerson>(sql, (bookWithPerson, person) => { bookWithPerson.Pers = person; return bookWithPerson; }, book); //splitOn: "bookName"); return (BookWithPerson)result; } }
中,Query的三個泛型參數分別是委托回調類型1
,委托回調類型2
,返回類型
。形參的三個參數分別是sql語句
,map委托
,對象參數
。所以整句的意思是先根據sql語句查詢;同時把查詢的Area信息賦值給bookWithArea.Pers,並且返回bookWithArea;book是對象參數,提供參數綁定的值。
最終整個方法返回BookWithArea,這樣我們所需要的所有信息就有了。
這裡只是簡單介紹下同步增刪改查的API的書寫,非同步的API,可以自行去瞭解。
參考地址:https://www.cnblogs.com/flywong/p/9666963.html