上一篇, 提到Query<Test>查询的时候, 如果Test中包含自定义class, Dapper不会给自定义class完成映射, 而是直接给null, 其实是可以实现的, 答案就在下面的基本用法介绍中
提到用法, 首先是要实现CURD, 这里先介绍Read吧.
先上实体:
public enum Gender { 男 = 0, 女 } public class Tch_Teacher { public int Id { get; set; } public Gender Sex { get; set; } public string Name { get; set; } public bool IsDoublePosition { get; set; } public DateTime CreateDate { get; set; } } public class Tch_Contact { public int Id { get; set; } public int TId { get; set; } public string Phone { get; set; } public string QQ { get; set; } public string Weixin { get; set; } } public class TeacherInfo { public Tch_Contact Contact { get; set; } public Tch_Teacher Teacher { get; set; } }
一、一对一映射
var sql = string.Empty; sql = "select Count(1) from tch_teacher where id>@Id limit 3;"; Console.WriteLine(conn.Query<int>(sql, new { Id = 10 })); Console.WriteLine(conn.Query<string>(sql, new { Id = 1 })); sql = "select Sex, Id, Name, CreateDate, No from tch_teacher limit 3;"; var list = conn.Query<Test>(sql);
var list1 = conn.Query<object>(sql);
var list2 = conn.Query<dynamic>(sql); Console.WriteLine(list.ToList().FirstOrDefault().Name);
一对一映射还是蛮简单的, 不需要解释了, 这种写法, 就是前面提到的, 如果Tch_Teacher里面有一个Tch_Contact类型的属性, 那么在映射的时候, 这个属性会直接赋值为null
二、一对多映射
sql = @"select a.Id, a.Sex, a.Name, a.CreateDate, a.No, b.Id, b.Phone, b.QQ,
b.Weixin from tch_teacher a left join tch_contact b on a.Id = b.TId order by a.Id asc limit 3;"; //No这个字段, 在类中并没有 var list1 = conn.Query<Test, Tch_Contact, TeacherInfo>(sql, (a, b) => { TeacherInfo tInfo = new TeacherInfo(); if (a != null) { tInfo.Teacher = a; } if (b != null) { tInfo.Contact = b; } return tInfo; }); //}, null, null, true, "Id", null, null);
此时, 返回的 List<TeacherInfo> 中, Teacher 和 Contact 都是有值的, 而不是直接给null, 当然, TeacherInfo中, 还可以有别的字段, 比如 public int No {get;set;},
此时的No是能获取到值的. 其中的映射原理, 这里我就不再赘述了, 能看懂Dapper中一对一映射的原理, 一对多映射也就差不多了.
如果将 TeacherInfo类中Contact属性修改一下, 改成 List<Tch_Contact>类型, 那么怎样得到一个按 Tch_Teacher 分组的数据呢?
通常情况下, 会想到两种办法:
一种是上面这种办法, 先得到全部数据, 然后通过GroupBy方法, 进行分组, 也能得到那种分组数据, 但那并不理想, 这种方法我就不贴了.
1. 得到的数据, 并不是我们想要的那种格式数据, 虽然也是分组的数据.
2. 有重复项. Tch_Teacher并没有得到去除重复的功能. 虽然分了组, 但是每组中的数据, Tch_Teacher仍然是重复的.
另一种, 就是通过一个中间变量来获取, 方法如下:
sql = @"select a.Id, a.Sex, a.Name, a.CreateDate, a.No, b.Id, b.Phone, b.QQ, b.Weixin from tch_teacher a left join tch_contact b on a.Id = b.TId order by a.Id asc limit 6;"; var infos = new Dictionary<int, TeacherInfo>(); var list1 = conn.Query<Test, Tch_Contact, TeacherInfo>(sql, (a, b) => { TeacherInfo tInfo; if (!infos.TryGetValue(a.Id, out tInfo)) { tInfo = new TeacherInfo(); tInfo.Contact = new List<Tch_Contact>(); tInfo.Teacher = a; infos.Add(a.Id, tInfo); } if (b != null) { infos[a.Id].Contact.Add(b); } return infos[a.Id]; });
使用字典项, 在其中进行一个规整操作, 去除重复的 Tch_Teacher信息, 把Tch_Contact进行规整分组. 而且, 得到的结果, 就直接是想要的结果
public class TeacherInfo { public List<Tch_Contact> Contact { get; set; } public Tch_Teacher Teacher { get; set; } }
话说回来, 至于最终使用哪种方法, 要根据具体使用需求来定, 总体来说, 都能达到效果. 方法无好坏, 只是使用场景不同.