Dapper2.0.78手册翻译

Dapper - .Net下的一个简单的ORM框架

特性

Dapper是一个NuGet库,你可以把它添加到你的项目中,扩展你的IDbConnection接口。

提供了3个方法

查询并映射一个实例集合

public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

 使用例子

public class Dog
{
    public int? Age { get; set; }
    public Guid Id { get; set; }
    public string Name { get; set; }
    public float? Weight { get; set; }

    public int IgnoredProperty { get { return 1; } }
}

var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });

Assert.Equal(1,dog.Count());
Assert.Null(dog.First().Age);
Assert.Equal(guid, dog.First().Id);

 查询并映射成dynamic集合

public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

 使用例子

var rows = connection.Query("select 1 A, 2 B union all select 3, 4").AsList();

Assert.Equal(1, (int)rows[0].A);
Assert.Equal(2, (int)rows[0].B);
Assert.Equal(3, (int)rows[1].A);
Assert.Equal(4, (int)rows[1].B);

 执行无返回结果的sql语句

public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)

 使用例子

var count = connection.Execute(@"
  set nocount on
  create table #t(i int)
  set nocount off
  insert #t
  select @a a union all select @b
  set nocount on
  drop table #t", new {a=1, b=2 });
Assert.Equal(2, count);

 插入多个实例对象

var count = connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
  );
Assert.Equal(3, count); // 3 rows inserted: "1,1", "2,2" and "3,3"

带参数查询

参数为一个匿名类

new {A = 1, B = "b"} // A will be mapped to the param @A, B to the param @B

 Dapper允许你传入IEnumerable<int>,并将自动参数化你的查询。

connection.Query<int>("select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids", new { Ids = new int[] { 1, 2, 3 } });
相当于执行 select * from (select 1 as Id union all select 2 union all select 3) as X where Id in (@Ids1, @Ids2, @Ids3)" // @Ids1 = 1 , @Ids2 = 2 , @Ids2 = 3

类型转换

Dapper 支持bool和numeric的自动转换

connection.Query("select * from User where UserTypeId = {=Admin}", new { UserTypeId.Admin });

多实例映射

class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public User Owner { get; set; }
}

class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}
var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id";

var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});
var post = data.First();

Assert.Equal("Sams Post1", post.Content);
Assert.Equal(1, post.Id);
Assert.Equal("Sam", post.Owner.Name);
Assert.Equal(99, post.Owner.Id);

假设做一个连接查询,将User对象放入Post对象更有意义。将user对象放入Post对象写法

 (post, user) => { post.Owner = user; return post; }

Dapper可以通过假设Id列的名称为Id或Id来分割返回的行。如果主键不同,或者希望在Id以外的点分割行,可以使用可选的splitOn参数。

多结果查询

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();
}

 存储过程

一般写法

var user = cnn.Query<User>("spGetUser", new {Id = 1},
        commandType: CommandType.StoredProcedure).SingleOrDefault();

第二种写法

var p = new DynamicParameters();
p.Add("@a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

cnn.Execute("spMagicProc", p, commandType: CommandType.StoredProcedure);

int b = p.Get<int>("@b");
int c = p.Get<int>("@c");

 Ansi 字符串和varchar字符串

Dapper支持varchar参数,如果你在varchar列上使用一个参数执行where子句,请确保以这样的方式传递它:

Query<Thing>("select * from Thing where Name = @Name", new {Name = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = true });

 在SQL Server上,查询unicode时使用unicode,查询非unicode时使用ANSI是至关重要的。

每行数据的类型切换

通常,您希望将给定表中的所有行视为相同的数据类型。但是,在某些情况下,能够将不同的行解析为不同的数据类型是很有用的。这是IDataReader的位置。GetRowParser可以派上用场。

假设您有一个名为“Shapes”的数据库表,列为:Id、Type和Data,您希望根据Type列的值将其行解析为CircleSquareTriangle对象。

var shapes = new List<IShape>();
using (var reader = connection.ExecuteReader("select * from Shapes"))
{
    // Generate a row parser for each type you expect.
    // The generic type <IShape> is what the parser will return.
    // The argument (typeof(*)) is the concrete type to parse.
    var circleParser = reader.GetRowParser<IShape>(typeof(Circle));
    var squareParser = reader.GetRowParser<IShape>(typeof(Square));
    var triangleParser = reader.GetRowParser<IShape>(typeof(Triangle));

    var typeColumnIndex = reader.GetOrdinal("Type");

    while (reader.Read())
    {
        IShape shape;
        var type = (ShapeType)reader.GetInt32(typeColumnIndex);
        switch (type)
        {
            case ShapeType.Circle:
            	shape = circleParser(reader);
            	break;
            case ShapeType.Square:
            	shape = squareParser(reader);
            	break;
            case ShapeType.Triangle:
            	shape = triangleParser(reader);
            	break;
            default:
            	throw new NotImplementedException();
        }

      	shapes.Add(shape);
    }
}

 MySql中使用自定义变量

为 了在MySql中使用不带参数的sql,必须在连接字符串中使用Allow User Variables=True

限制与警告

Dapper会缓存运行查询结果,这允许它快速实体化对象和快速处理参数。当前实现将此信息缓存到ConcurrentDictionary对象中。只使用过一次的语句将定期从该缓存中刷新。但是,如果您在不使用参数的情况下动态生成SQL语句,则可能会遇到内存问题。

Dapper不包含数据库实现细节,它依赖于包括SQLite, SQL CE, Firebird, Oracle, MySQL, PostgreSQL和SQL Server的ADO.NET Provider。

Dapper只是简单的ORM框架,解决95%的应用问题,不试图解决所有问题

Dapper.Contrib -  dapper的扩展

特性

Dapper.Contrib 包含插入、获取、更新和删除记录的方法。

以下是Dapper.Contrib包含的全部扩展方法清单:

T Get<T>(id);
IEnumerable<T> GetAll<T>();
int Insert<T>(T obj);
int Insert<T>(Enumerable<T> list);
bool Update<T>(T obj);
bool Update<T>(Enumerable<T> list);
bool Delete<T>(T obj);
bool Delete<T>(Enumerable<T> list);
bool DeleteAll<T>();

如果实体模型存在Id属性,Dapper会默认Id属性为主键。

public class Car
{
    public int Id { get; set; } // Works by convention
    public string Name { get; set; }
}

如果实体模型不遵循包含Id属性,则必须在主键属性上加一个[Key] 或者 [ExplicitKey]特性。

public class User
{
    [Key]
    int TheId { get; set; }
    string Name { get; set; }
    int Age { get; set; }
}

 [Key] 使用的时候,该属性必须是数据库主键并是自增。

[ExplicitKey] 只是在代码中作为主键,使用场景是数据库里面不是自增字段,在代码模型中作为主键使用。

Get 方法

根据Id获取实体数据

var car = connection.Get<Car>(1);

获取表中所有的实体数据

var cars = connection.GetAll<Car>();

 Insert 方法

插入一个实体

connection.Insert(new Car { Name = "Volvo" });

插入多个实体

connection.Insert(cars);

 Update 方法

更新一个实体

connection.Update(new Car() { Id = 1, Name = "Saab" });

更新多个实体

connection.Update(cars);

 Delete 方法

根据Id删除实体

connection.Delete(new Car() { Id = 1 });

删除多个实体

connection.Delete(cars);

删除全部实体

connection.DeleteAll<Car>();

 其他特性

Dapper.Contrib 中的其他Atribute:

[Table("Tablename")] - 当表名和实体类名不一样,可使用该Atribute知名数据库中的表名

[Table ("emps")]
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

 [Key] - 当数据库中没有自增Id的时候,使用Key这个Atribute来指明自增和主键字段

public class Employee
{
    [Key]
    public int EmployeeId { get; set; }
    public string Name { get; set; }
}

 [ExplicitKey] - 当数据库中没有自增字段,使用该Atribute来指明主键字段

public class Employee
{
    [ExplicitKey]
    public Guid EmployeeId { get; set; }
    public string Name { get; set; }
}
  • [Write(true/false)] - 该Atribute来指明是否写数据库true为写,false为不写

  • [Computed] - 这个Atribute来指明不用更新数据库的字段

    限制与警告

  • SQLite

  • SQLiteConnection公开了一个与Dapper.Contrib提供的更新扩展冲突的更新事件。有两种方法可以解决这个问题。
  • 1、从SqlMapperExtensions显式调用Update方法
  • SqlMapperExtensions.Update(_conn, new Employee { Id = 1, Name = "Mercedes" });
    

    2、使用一个类型参数来保证方法签名的唯一

  • connection.Update<Car>(new Car() { Id = 1, Name = "Maruti" });
    
原文地址:https://www.cnblogs.com/CelonY/p/14220203.html