Dapper的使用

背景

在一个unity应用中想要使用数据库,
然而Monobehaviour的用法看起来太过底层,
于是用一个稍微高一点的工具.

简介

一个开源的,轻量的ORM框架.
特点: 简单地将Reader中的内容,通过反射机制,制造成对象.还支持一对多关系.

优点:

  1. 性能好,通过Emit反射IDataReader来生产对象.
  2. 语法简单
  3. 编译后占用空间小

缺点:

  1. 不是一个完整的解决方案,依然基于SQL语句

简单使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
IDbConnection connection = new SqlConnection("URI=file:./MyData.db");

// 插入,当然也可以将user类单独拿出来,做成模型
var result = connection.Execute("INSERT INTO users VALUES (@id, @name,@password)",
new { id = 1, name = "jack", password = "123456"});

// 批量插入
var result = connection.Execute("insert into UserInfo(Address,Name) values(@address,@name)",
new[] {
new { Address = "上海", Name = "李四" },
new { Address = "北京", Name = "王五" },
new { Address = "杭州", Name = "赵六" }
});

// 查询一个
User testUser = connection.Query<User>("SELECT id, name FORM users WHERE name = @name",
new {name = "test"}).FirstOrDefault();

// 查询多个
IEnumerable<User> targetUsers = connection.Query<User>("SELECT id, name FORM users WHERE name like \"%@param%\"",
new {param = "test"});

// 更新
connection.Execute("UPDATE users SET name=@name where id=@id", new {id=12, name="test"});

// 删除
connection.Execute("DELETE FROM users WHERE name = @name", new {name="test"});

高级一些的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// in写法
conn.Query<Users>("SELECT * FROM Users s WHERE s.id IN (@ids) ",new { ids = new int[]{1,2,3}})

// 多结果查询
multi = connection.QueryMultiple("SELECT * FROM books; SELECT * FROM users");
IEnumerable<Book> books = multi.Read<Book>();
IEnumerable<User> users = multi.Read<User>();

// 表关联查询
public class BookWithPerson
{
public int ID { get; set; }
public Person Pers { get; set; }
public string BookName { get; set; }
}

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> // 委托类型1,委托类型2,返回值类型
(sql,(bookWithPerson, person) =>
{
bookWithPerson.Pers = person;
return bookWithPerson;
},
book);

return (BookWithPerson)result;
}
}

目前了解的函数有

  • Query 一般的查询
  • Execute 一般的执行
  • QueryMultiple 多语句查询
  • QueryFirst 查询第一个,如果没有会报错
  • QueryFirstOrDefault 查询第一个,为空不报错并返回null
  • QuerySingle 查询一个,与First不同的是,如果得到多个会报错,同时查出为空也报错
  • QuerySingleOrDefault 查询一个,为空不报错并返回null

包装使用

显然处处使用

1
2
3
4
5
6
using (IDbConnection connection = new SqlConnection(connectionString))
{
var sql = "SELECT * FROM users where id=@id";
User result = connection.Query<User>(sql, new {id = 123});
return result;
}

也并不是一个通用的办法,最好包装一下,分别放到不同的文件里

这里有一种包装的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 最底层
namespace Dao {
public class SQLHelper {

private string _Connstring;

public SQLHelper() {
_Connstring = string.Format("URI=file:{0}/Data/{1}", Application.dataPath, "unity_test.db");
}

// 参数类型是一个函数sqlExcutor
// 函数sqlExcutor 参数类型是IDbConnection, 返回类型是T
// connection在此处就准备好了,但拿这个conn来做什么,需要具体定义出来
private T SQLExcute<T>(Func<IDbConnection, T> sqlExcutor) {
using (IDbConnection conn = new SqliteConnection(_Connstring)) {
conn.Open();
return sqlExcutor(conn);
}
}

public IEnumerable<T> Query<T>(string SqlText, object para = null) {
// 该函数用conn来执行Query函数
// 当然也可以用来执行其他的QueryFirst,QueryFirstOrDefault,QuerySingle,QuerySingleOrDefault
return SQLExcute((conn) => conn.Query<T>(SqlText, para));
}

public int Excute(string SqlText, object para = null) {
// 该函数用conn来执行Execute函数
return SQLExcute((conn) => conn.Execute(SqlText, para));
}
}
}

// 模型
namespace Model {
public class Patient {

public int id { get; set; }
public string name { get; set; }
public int age { get; set; }
}
}

// 查询接口
namespace Dao {
public class PatientDao {
private SQLHelper _sqlHelper = new SQLHelper();

public static IEnumerable<Patient> All() {
string sqlText = "SELECT id,name,age From patients";
return _sqlHelper.Query<Patient>(sqlText, null);
}
}
}

// 使用
List patients = PatientDao.All().ToList();

其他注意

如果在unity中使用,需要下载dll放入Assets/Plugin文件夹下

  1. Dapper.dll(可以从网上下载,但要注意如果版本太旧,不能使用QuerySingle等API)
  2. Mono.Data.Sqlite.dll(unity自带一些)
  3. sqlite3.dll(sqlite官网可下载,但webgl中不支持使用sqlite)

参考

  1. 简单介绍
  2. 入门使用
  3. join使用
  4. 包装使用