Slapper帮助Dapper实现一对多
Dapper的Query的方法提供了多个泛型重载可以帮助我们实现导航属性的查询
1对1
public class Employees4List { public int Id { get; set; } public string Name { get; set; } public string Mobile { get; set; } public Department4Employees Department { get; set; } } public class Role4Employees { public int Id { get; set; } public string Name { get; set; } } IEnumerable<Employees4List> GetEmployees() { var sql = $@" select #e.[Id],#e.[Name],#e.[Mobile] ,#depart.id,#depart.name from dbo.T_Eemploye #e left join [dbo].[T_Department] #depart on #depart.id = #e.Department "; using (var conn = GetReadConnection()) { var list = conn.Query<Employees4List, Department4Employees, Employees4List>(sql, (e, d) => { e.Department = d; return e; }); return list; } }
1对n
但是如果职工类中加入这样一个属性呢 ? public List<Role4Employees> Role { get; set; }
public class Employees4List { public int Id { get; set; } public string Name { get; set; } public string Mobile { get; set; } public List<Role4Employees> Role { get; set; } public Department4Employees Department { get; set; } } public class Role4Employees { public int Id { get; set; } public string Name { get; set; } } public class Department4Employees { public int Id { get; set; } public string Name { get; set; } }
之前看到过这样一个方式,但是它是不能像我们想象的那样工作,这里如果一个Eemploye有多个角色,那就和原始的sql语句一样,他会产生重复的记录
IEnumerable<Employees4List> GetEmployees() { var sql = $@" select #e.[Id],#e.[Name],#e.[Mobile] ,#depart.id,#depart.name ,#role.id,#role.name from dbo.T_Eemploye #e left join [dbo].[T_Department] #depart on #depart.id = #e.Department left join [dbo].[T_Role] #role on #role.value & #e.role = #role.value "; using (var conn = GetReadConnection()) { var list = conn.Query<Employees4List, Department4Employees, Role4Employees, Employees4List>(sql,(e, d, r) => { e.Department = d; e.Role.Add(r); return e; }); return list; } }
正确的方式是使用Slapper.Automapper,这个包需要独立安装
IEnumerable<Employees4List> GetEmployees() { var sql = $@" select #e.[Id],#e.[Name],#e.[Mobile] ,#role.id Role_Id,#role.name Role_Name ,#depart.id Department_Id,#depart.name Department_Name from dbo.T_Eemploye #e left join [dbo].[T_Role] #role on #role.value & #e.role = #role.value left join [dbo].[T_Department] #depart on #depart.id = #e.Department "; using (var conn = GetReadConnection()) { var dynamic = conn.Query<dynamic>(sql); Slapper.AutoMapper.Configuration.AddIdentifiers(typeof(Employees4List), new List<string> { "Id" }); Slapper.AutoMapper.Configuration.AddIdentifiers(typeof(Role4Employees), new List<string> { "Id" }); Slapper.AutoMapper.Configuration.AddIdentifier(typeof(Department4Employees), "Id"); var list = (Slapper.AutoMapper.MapDynamic<Employees4List>(dynamic) as IEnumerable<Employees4List>).ToList(); return list; } }
通过AddIdentifier和AddIdentifier来识别外键是1对1还是1对n,需要注意的是这里需要对字段取别名,怎么取呢?
新的名称以在c#类中字段名称+下划线+导航类的字段名称
比如说Employees4List中有一个属性Role要做1对n查询,通过AddIdentifiers方法指明需要转换的类型名称和主键名称,其次在sql语句中通过
Role_Id和Role_Name来取别名,下划线前面的Role来自Employees4List的 Role属性,下划线后面的 Id 和 Name来自 Role4Employees