publicstaticIEnumerable<TReturn>Query<TFirst,TSecond,TReturn>( #if CSHARP30 thisIDbConnection cnn,string sql,Func<TFirst,TSecond,TReturn>map,object param,IDbTransaction transaction, bool buffered,string splitOn,int? commandTimeout,CommandType? commandType #else thisIDbConnection cnn,string sql,Func<TFirst,TSecond,TReturn>map,object param =null,IDbTransaction transaction =null, bool buffered =true,string splitOn ="Id",int? commandTimeout =null,CommandType? commandType =null #endif )
IDbConnection 的扩展方法,泛型: < TFirst , TSecond , TReturn > 传入sql,Func委托: Func < TFirst , TSecond , TReturn > 实例代码中为:
(post, user)=>{ post.Owner= user;return post;}
意思是,通过第一个和第二个类型得出返回类型对象。本例中 TFirst -> PostWithConstructor, TSecond-> UserWithConstructor, TReturn-> PostWithConstructor
看一下结果:
注意下 TFirst, TSecond 的顺序,以及sql连表的顺序,换成右链接:
连表的顺序和传入的顺序非常重要;
这里注意一个问题:这个结果集的字段和实体的属性名称不相同,那是怎么映射的?如果有同名的属性怎么去处理?
我们注意到返回的结果集有重名字段,重名字段Id是对应不同的表的,用select * 这样可以把不同表的字段全部取出来。同时注意了,数据库表中的字段和实体Model里的属性名并不一致,其实他们是根据Model实体的构造函数进行区分的,我们可以看到这两个model都有构造函数:
dapper用结果集列名作区分,如何区分哪几列是一张表呢?dapper规定了分割字段,按分割的字段名进行对列的分割,默认的分割字段名为:Id,可以手动指定,基于这个原因就有了另外一个规定:分割字段必须是这个表的第一个字段。对于如下表设计就会报错。
dapper现在可以将结果集5列进行区分为两个表了,这时候对应哪个Model就要看传入 TFirst, TSecond 的顺序。 注意一下 PostWithConstructor 的构造函数的owerid参数,这个参数在构造函数中并未使用,但是也标明了它,因为根据分割字段“Id"区分出给 PostWithConstructor 实体这三个:Id,OwnerId,[Content]字段。所以必须要在构造函数中有这三个字段的匹配。即 : System.Int32 Id, System.Int32 OwnerId, System.String Content,不区分大小写。