訪問量不大的項目我都是用EF寫數據庫操作,因為EF除了速度上慢以外,但開發效率極快,省略了很多sql寫法,並能很方便的調用外鍵、集合等信息,用EF寫項目最爽的事。不過有些項目網站要考慮運行速度,這時不得不用其它的ORM框架,我常用dapper,因為它效果快,而且寫sql非常靈活,接下來面寫一些方法看看dapper的使用
1、連接語句
var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlDiagnosticsDb"].ConnectionString);
使用dapper不需要考慮conn是否連接,在執行dapper時自行判斷 open狀態,如果沒有打開它會自己打開。
2、insert
string query = "INSERT INTO Book(Name)VALUES(@name)"; conn.Execute(query, book);
book類中有name屬性,就可以這樣方便去寫,當然也可以寫成
string query = "INSERT INTO Book(Name)VALUES(@name)"; conn.Execute(query, new{@name=book.name});
3、update
string query = "UPDATE Book SET Name=@name WHERE id =@id"; conn.Execute(query, book);
4、 delete
string query = "DELETE FROM Book WHERE id = @id"; conn.Execute(query, book); conn.Execute(query, new { id = id });
5、query
string query = "SELECT * FROM Book"; //無參數查詢,返回列表,帶參數查詢和之前的參數賦值法相同。 conn.Query<Book>(query).ToList(); //返回單條信息 string query = "SELECT * FROM Book WHERE id = @id"; book = conn.Query<Book>(query, new { id = id }).SingleOrDefault();
6、 傳統sql in (1,2,3) 用dapper就這樣寫
conn.Query<Users>("SELECT * FROM Users s WHERE s.id IN (@ids) ",new { ids = new int[]{1,2,3}}) conn.Query<Users>("SELECT * FROM Users s WHERE s.id IN (@ids) ",new { ids = IDs.ToArray()})
在dapper因為安全性,不能直接用sql接接 要采用參數化,
7、批量插入
conn.Execute(@"insert MyTable(colA, colB) values (@a, @b)", new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } })
也可以直接寫入一個集合
conn.Execute("insert user(name) values(@name)",users)
這里users是一個user表的對象集合,可一次把集合中的所有數據插入到數據表中。
8、多表查詢
//查詢圖書時,同時查找對應的書評,並存在List中。實現1--n的查詢操作 string query = "SELECT * FROM Book b LEFT JOIN BookReview br ON br.BookId = b.Id WHERE b.id = @id"; Book lookup = null; //Query<TFirst, TSecond, TReturn> var b = conn.Query<Book, BookReview, Book>(query, (book, bookReview) => { //掃描第一條記錄,判斷非空和非重復 if (lookup == null || lookup.Id != book.Id) lookup = book; //書對應的書評非空,加入當前書的書評List中,最后把重復的書去掉。 if (bookReview != null) lookup.Reviews.Add(bookReview); return lookup; }, new { id = id }).Distinct().SingleOrDefault(); return b;
多表聯合查詢是比較麻煩一些,到現在不是完全明白,多看幾個例子
var sql = @"select * from Posts p join Users u on u.Id = p.OwnerId Order by p.Id"; var data = conn.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;},splitOn:"id");
Post類和User類,它們存在外鍵, conn.Query返回的類型是最后一個參數Post, 其中Post中有一屬性Owner是User對象,在(post, user)=>lamda中指定了Owner值,上邊的代碼中的
splitOn
是ID,運行時,會從查詢結果所有字段列表的最后一個字段開始進行匹配,一直到找到Id這個字段(大小寫忽略),找到的第一個ID字段匹配
User類的ID屬性,那么從ID到最后一個字段都屬於
User,ID以前的字段都被影射到
Post
, 通過
(post, user) => { return post;},
把兩個類的實例解析出來。
9、三表查詢,一個是關聯主鍵表(單個對象),一個是關聯外鍵表(集合)。
public partial class UserInfo { public UserInfo() { this.Persion = new HashSet<Persion>(); this.MyTYC = new HashSet<MyTYC>(); } public int id { get; set; } public string name { get; set; } public Nullable<System.DateTime> createTime { get; set; } public Movies Movies { get; set; } public virtual ICollection<MyTYC> MyTYC { get; set; } }
public class Movies { public int ID { get; set; } public string Title { get; set; } public string ReleaseDate { get; set; } public string Genre { get; set; } public string Price { get; set; } public UserInfo UserInfo { get; set; } }
public partial class MyTYC { public int id { get; set; } public string name { get; set; } }
string sql = @"select * from UserInfo u inner join [Movies].dbo.Movies m on u.id=m.ID inner join MyTYC t on u.id=t.id"; var data = conn.Query<UserInfo, Movies, MyTYC, UserInfo>(sql, (u, m, t) => { u.Movies = m; u.MyTYC.Add(t); return u; });
注意這里的對象和集合的獲取方法:u.Movies = m; u.MyTYC.Add(t);
10、多結果查詢
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(); }
再來一個
class Program { //創建連接對象 protected static SqlConnection GetConnection() { var connection = new SqlConnection("Data Source=.;Initial Catalog=TestDB;Integrated Security=True"); connection.Open(); return connection; } static void Main(string[] args) { //測試輸出多個結果集 var sql = @"INSERT INTO [dbo].[Student] ([Name]) VALUES ('A1'); select @@IDENTITY as A; INSERT INTO [dbo].[Student] ([Name]) VALUES ('B1'); select @@IDENTITY as A; INSERT INTO [dbo].[Student] ([Name]) VALUES ('C1'); select @@IDENTITY as A"; //初始化數據庫連接 using (SqlConnection connection = GetConnection()) { List<int> ilist = new List<int>(); //執行查詢,獲取結果集集合 var multi = connection.QueryMultiple(sql); //遍歷結果集 while(!multi.IsConsumed) { //讀取當前結果集 var result = multi.Read().ToList()[0].A; if (result != null) { ilist.Add(Convert.ToInt32(result)); } } //for(int i = 0;i<3;i++) //{ // var result = multi.Read().ToList()[0].A; // if (result != null) // { // ilist.Add(Convert.ToInt32(result)); // } //} foreach (var item in ilist) { Console.WriteLine(item.ToString()); } } Console.ReadLine(); } }
11、如果某一代碼中多次操作數據庫,可以把conn設置為打開,最后時再close,
比如:
conn.open() conn.Query(..... ..... for.... ..... conn.close()