Dapper是.NET下一個micro的ORM,它和Entity Framework或Nhibnate不同,屬於輕量級的,並且是半自動的。也就是說實體類都要自己寫。它沒有復雜的配置文件,一個單文件就可以了。給出官方地址。
http://code.google.com/p/dapper-dot-net/
個人覺得他非常好用,現在已經取代了原來的SqlHelper。優點:
- 使用Dapper可以自動進行對象映射!
- 輕量級,單文件。
- 支持多數據庫。
- Dapper原理通過Emit反射IDataReader的序列隊列,來快速的得到和產生對象。
網上還有對Dapper的擴展類,這里就不贅述了。下面只講下簡單的增刪改查、數據庫表間的對應關系和事務的應用。
先給出實體類的關系:
書和書評是1---n的關系。(沿用Entity Framework的實體類,virtual表示延遲加載,此處忽略)
//書 public class Book { public Book() { Reviews = new List<BookReview>(); } public int Id { get; set; } public string Name { get; set; } public virtual List<BookReview> Reviews { get; set; } public override string ToString() { return string.Format("[{0}]------《{1}》", Id, Name); } } //書評 public class BookReview { public int Id { get; set; } public int BookId { get; set; } public virtual string Content { get; set; } public virtual Book AssoicationWithBook { get; set; } public override string ToString() { return string.Format("{0})--[{1}]\t\"{3}\"", Id, BookId, Content); } }
- 基本的增刪改查操作
由於Dapper ORM的操作實際上是對IDbConnection類的擴展,所有的方法都是該類的擴展方法。所以在使用前先實例化一個IDBConnection對象。
IDbConnection conn = new SqlConnection(connString);
Insert
Book book = new Book();
book.Name="C#本質論"; string query = "INSERT INTO Book(Name)VALUES(@name)"; //對對象進行操作 conn.Execute(query, book); //直接賦值操作 conn.Execute(query, new {name = "C#本質論"});
update
string query = "UPDATE Book SET Name=@name WHERE id =@id"; conn.Execute(query, book);
delete
string query = "DELETE FROM Book WHERE id = @id"; conn.Execute(query, book); conn.Execute(query, new { id = id });
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();
- 數據庫表對應關系操作
//查詢圖書時,同時查找對應的書評,並存在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;
//1--1操作 BookReview br; string query = "SELECT * FROM BookReview WHERE id = @id"; using (conn) { br = conn.Query<BookReview, Book, BookReview>(query, (bookReview, book) => { bookReview.AssoicationWithBook = book; return bookReview; }, new { id = id }).SingleOrDefault(); return br; }
- 事務操作
using (conn)
{
//開始事務 IDbTransaction transaction = conn.BeginTransaction(); try { string query = "DELETE FROM Book WHERE id = @id"; string query2 = "DELETE FORM BookReview WHERE BookId = @BookId"; conn.Execute(query2, new { BookId = id }, transaction, null, null); conn.Execute(query, new { id = id }, transaction, null, null); //提交事務 transaction.Commit(); } catch (Exception ex) { //出現異常,事務Rollback transaction.Rollback(); throw new Exception(ex.Message); } }
Dapper.NET——輕量ORM
Dapper.NET使用
本文目錄
Dapper是一款輕量級ORM工具(Github)。如果你在小的項目中,使用Entity Framework、NHibernate 來處理大數據訪問及關系映射,未免有點殺雞用牛刀。你又覺得ORM省時省力,這時Dapper 將是你不二的選擇。
1、為什么選擇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
2、以Dapper(4.0)為例。
2.1 在數據庫中建立幾張表。
CREATE TABLE [dbo].[CICUser]
(
[UserId] [int] IDENTITY(1, 1) PRIMARY KEY NOT NULL,
[Username] [nvarchar](256) NOT NULL,
[PasswordHash] [nvarchar](500) NULL,
[Email] [nvarchar](256) NULL,
[PhoneNumber] [nvarchar](30) NULL,
[IsFirstTimeLogin] [bit] DEFAULT(1) NOT NULL,
[AccessFailedCount] [int] DEFAULT(0) NOT NULL,
[CreationDate] [datetime] DEFAULT(GETDATE()) NOT NULL,
[IsActive] [bit] DEFAULT(1) NOT NULL
)
CREATE TABLE [dbo].[CICRole]
(
[RoleId] [int] IDENTITY(1, 1) PRIMARY KEY NOT NULL,
[RoleName] [nvarchar](256) NOT NULL,
)
CREATE TABLE [dbo].[CICUserRole]
(
[Id] [int] IDENTITY(1, 1) PRIMARY KEY NOT NULL,
[UserId] [int] FOREIGN KEY REFERENCES [dbo].[CICUser] ([UserId]) NOT NULL,
[RoleId] [int] FOREIGN KEY REFERENCES [dbo].[CICRole] ([RoleId]) NOT NULL
)
2.2實體類。
在創建實體類時,屬性名稱一定要與數據庫字段一一對應。
實體類
3.使用方法
3.1 一對一映射
private static void OneToOne(string sqlConnectionString)
{
List<Customer> userList = new List<Customer>();
using (IDbConnection conn = GetSqlConnection(sqlConnectionString))
{
string sqlCommandText = @"SELECT c.UserId,c.Username AS UserName,
c.PasswordHash AS [Password],c.Email,c.PhoneNumber,c.IsFirstTimeLogin,c.AccessFailedCount,
c.CreationDate,c.IsActive,r.RoleId,r.RoleName
FROM dbo.CICUser c WITH(NOLOCK)
INNER JOIN CICUserRole cr ON cr.UserId = c.UserId
INNER JOIN CICRole r ON r.RoleId = cr.RoleId";
userList = conn.Query<Customer, Role, Customer>(sqlCommandText,
(user, role) => { user.Role = role; return user; },
null,
null,
true,
"RoleId",
null,
null).ToList();
}
if (userList.Count > 0)
{
userList.ForEach((item) => Console.WriteLine("UserName:" + item.UserName +
"----Password:" + item.Password +
"-----Role:" + item.Role.RoleName +
"\n"));
Console.ReadLine();
}
}
3.2 一對多映射
private static void OneToMany(string sqlConnectionString)
{
Console.WriteLine("One To Many");
List<User> userList = new List<User>();
using (IDbConnection connection = GetSqlConnection(sqlConnectionString))
{
string sqlCommandText3 = @"SELECT c.UserId,
c.Username AS UserName,
c.PasswordHash AS [Password],
c.Email,
c.PhoneNumber,
c.IsFirstTimeLogin,
c.AccessFailedCount,
c.CreationDate,
c.IsActive,
r.RoleId,
r.RoleName
FROM dbo.CICUser c WITH(NOLOCK)
LEFT JOIN CICUserRole cr
ON cr.UserId = c.UserId
LEFT JOIN CICRole r
ON r.RoleId = cr.RoleId";
var lookUp = new Dictionary<int, User>();
userList = connection.Query<User, Role, User>(sqlCommandText3,
(user, role) =>
{
User u;
if (!lookUp.TryGetValue(user.UserId, out u))
{
lookUp.Add(user.UserId, u = user);
}
u.Role.Add(role);
return user;
}, null, null, true, "RoleId", null, null).ToList();
var result = lookUp.Values;
}
if (userList.Count > 0)
{
userList.ForEach((item) => Console.WriteLine("UserName:" + item.UserName +
"----Password:" + item.Password +
"-----Role:" + item.Role.First().RoleName +
"\n"));
Console.ReadLine();
}
else
{
Console.WriteLine("No Data In UserList!");
}
}
3.3 插入實體
public static void InsertObject(string sqlConnectionString)
{
string sqlCommandText = @"INSERT INTO CICUser(Username,PasswordHash,Email,PhoneNumber)VALUES(
@UserName,
@Password,
@Email,
@PhoneNumber
)";
using (IDbConnection conn = GetSqlConnection(sqlConnectionString))
{
User user = new User();
user.UserName = "Dapper";
user.Password = "654321";
user.Email = "Dapper@infosys.com";
user.PhoneNumber = "13795666243";
int result = conn.Execute(sqlCommandText, user);
if (result > 0)
{
Console.WriteLine("Data have already inserted into DB!");
}
else
{
Console.WriteLine("Insert Failed!");
}
Console.ReadLine();
}
}
3.4 執行存儲過程
/// <summary>
/// Execute StoredProcedure and map result to POCO
/// </summary>
/// <param name="sqlConnnectionString"></param>
public static void ExecuteStoredProcedure(string sqlConnnectionString)
{
List<User> users = new List<User>();
using (IDbConnection cnn = GetSqlConnection(sqlConnnectionString))
{
users = cnn.Query<User>("dbo.p_getUsers",
new { UserId = 2 },
null,
true,
null,
CommandType.StoredProcedure).ToList();
}
if (users.Count > 0)
{
users.ForEach((user) => Console.WriteLine(user.UserName + "\n"));
}
Console.ReadLine();
}
/// <summary>
/// Execute StroedProcedure and get result from return value
/// </summary>
/// <param name="sqlConnnectionString"></param>
public static void ExecuteStoredProcedureWithParms(string sqlConnnectionString)
{
DynamicParameters p = new DynamicParameters();
p.Add("@UserName", "cooper");
p.Add("@Password", "123456");
p.Add("@LoginActionType", null, DbType.Int32, ParameterDirection.ReturnValue);
using (IDbConnection cnn = GetSqlConnection(sqlConnnectionString))
{
cnn.Execute("dbo.p_validateUser", p, null, null, CommandType.StoredProcedure);
int result = p.Get<int>("@LoginActionType");
Console.WriteLine(result);
}
Console.ReadLine();
}

