Dapper实现一对多对象关系聚合导航属性
领域对象:Game(游戏), Room(游戏群),两者一对多的关系,SQL语句中会用到JOIN
public class Game : AggregateRoot
{
public string Tag { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public IEnumerable<Room> Rooms { get; set; } public Game()
{
this.Rooms = new HashSet<Room>();
} public void SetRooms(IEnumerable<Room> rooms)
{
this.Rooms = this.Rooms.Concat(rooms);
}
} public class Room : Entity
{
public int GameId{ get; set; }
public intstring Name { get; set; }
public int Limit { get; set; }
public string Owner { get; set; }
}
通常用Dapper的Query<TFirst,TSecond,TReturn>() 或 QueryAsync<TFirst,TSecond,TReturn>() 是可以实现,但是去除重复记录比较麻烦。
所以我们扩展两个Query/QueryAsync方法:
/// <summary>
/// 查询带聚合导航属性的对象集合
/// </summary>
/// <typeparam name="TFirst">主体对象类型</typeparam>
/// <typeparam name="TSecond">聚合导航对象类型</typeparam>
/// <param name="setting">设置聚合导航属性的方法</param>
public static IEnumerable<TFirst> Query<TFirst, TSecond>(this IDbConnection cnn, string sql, Action<TFirst, TSecond> setting, object param = null, string splitOn = "Id")
where TFirst : class, IEntity<int>
where TSecond : class, IEntity<int>
{
TFirst lookup = null;
var hashes = new HashSet<TFirst>();
cnn.Query<TFirst, TSecond, TFirst>(sql, (first, second) =>
{
//第一条记录,或者新的主体记录,否则lookup还是上一条记录
if (lookup == null || lookup.Id != first.Id)
lookup = first; if (second != null && second.Id > && setting != null)
setting(lookup, second); if (!hashes.Any(m => m.Id == lookup.Id))
hashes.Add(lookup); return null;
}, param: param, splitOn: splitOn); return hashes;
} /// <summary>
/// 异步查询带聚合导航属性的对象集合
/// </summary>
/// <typeparam name="TFirst">主体对象类型</typeparam>
/// <typeparam name="TSecond">聚合导航对象类型</typeparam>
/// <param name="setting">设置聚合导航属性的方法</param>
public static async Task<IEnumerable<TFirst>> QueryAsync<TFirst, TSecond>(this IDbConnection cnn, string sql, Action<TFirst, TSecond> setting, object param = null, string splitOn = "Id")
where TFirst : class, IEntity<int>
where TSecond : class, IEntity<int>
{
TFirst lookup = null;
var hashes = new HashSet<TFirst>();
await cnn.QueryAsync<TFirst, TSecond, TFirst>(sql, (first, second) =>
{
//第一条记录,或者新的主体记录,否则lookup还是上一条记录
if (lookup == null || lookup.Id != first.Id)
lookup = first; if (second != null && second.Id > && setting != null)
setting(lookup, second); if (!hashes.Any(m => m.Id == lookup.Id))
hashes.Add(lookup); return null;
}, param: param, splitOn: splitOn); return hashes;
}
调用示例:
return await _db.QueryAsync<Game, Room>("SELECT * FROM game g LEFT JOIN room r ON r.gameid = g.id", (game, room) =>
{
game.SetRooms(new HashSet<Room> { room });
}, splitOn: "Id");
Dapper实现一对多对象关系聚合导航属性的更多相关文章
- 关系与导航属性(摘自微软MSDN)
关系与导航属性 本主题概述实体框架如何管理实体间的关系.还对如何映射和操作关系提供了一些指南. 关系.导航属性和外键 在关系数据库中,表之间的关系(也称为关联)是通过外键定义的.外键 (FK) 是用于 ...
- Hibernate单向一对多对象关系模型映射
1 hibernate 的对象关系映射 Orm: 类-----表 属性------字段 对象------记录 表:在数据库中存在主外键的关系,反向工厂类是由表生成,在由表生成类的时候,类和类之间存在者 ...
- Hibernate双向一对多对象关系模型映射
双向one-to-many 描述部门和岗位:一个部门有多个岗位 将单向的one-to-many 和many-to-one合并. 4.1双向的one-to-many数据库模型 create table ...
- FreeSql (十八)导航属性
导航属性是 FreeSql 的特色功能之一,可通过约定配置.或自定义配置对象间的关系. 导航属性有 OneToMany, ManyToOne, ManyToMany, OneToOne, Parent ...
- MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式
文章索引和简介 通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种 ...
- FreeSql 导航属性的联级保存功能
写在前面 FreeSql 一个款 .net 平台下支持 .net framework 4.5+..net core 2.1+ 的开源 ORM.单元测试超过3100+,正在不断吸引新的开发者,生命不息开 ...
- MyBatis加强(1)~myBatis对象关系映射(多对一关系、一对多关系)、延迟/懒加载
一.myBatis对象关系映射(多对一关系.一对多关系) 1.多对一关系: ---例子:多个员工同属于一个部门. (1)myBatis发送 额外SQL: ■ 案例:员工表通过 dept_id 关联 部 ...
- [LINQ2Dapper]最完整Dapper To Linq框架(八)---导航属性
目录 [LINQ2Dapper]最完整Dapper To Linq框架(一)---基础查询 [LINQ2Dapper]最完整Dapper To Linq框架(二)---动态化查询 [LINQ2Dapp ...
- 《Entity Framework 6 Recipes》中文翻译系列 (27) ------ 第五章 加载实体和导航属性之关联实体过滤、排序、执行聚合操作
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-9 关联实体过滤和排序 问题 你有一实体的实例,你想加载应用了过滤和排序的相关 ...
随机推荐
- vue父传子
父组件传递数据给子组件用props,父组件中使用子组件,子组件用props接收父组件数据. Home父组件代码: <template> <div> {{test}} <! ...
- C[a,b]向量空间中的函数的线性相关性
- Solidity合约:玉米生产溯源
实现思路: 首先用地址与每个结构进行映射,将关键信息储存在结构体中:或者将关键信息在外部通过json储存,内部储存对应的hash值: 使用issue函数表示:玉米地中收获足够数量的玉米并进行记录: 使 ...
- Win7 IIS 部署站点遇到的问题 如 HTTP 错误 404.XX
HTTP 错误 404.2 - Not Found 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面. 解决办法:设置为允许-面相 =============== ...
- Visual C++实现局域网IP多播
//////////////////////////////////////////////////////////////////////////////////////////////////// ...
- Ng第五课:Octave 教程(Octave Tutorial)
5.1 基本操作 5.2 对数据进行灵活操作 5.3 计算数据 5.4 数据可视化 5.5 控制语句和函数 5.6 矢量化 官网安装:Installation 在线文档:http://ww ...
- javascript的Mixins
mixin在javascript里可以看作是一种从别的对象"借用"功能的方法.每一个新定义的对象都有一个 prototype属性,其他的对象就可以从这里"借用" ...
- OkHttp3几个简单的例子和在子线程更新UI线程的方法
okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿. ...
- 14:super关键字
本小节知识点: 1.super基本概念 2.super的作用 1.super基本概念 super是个编译器的指令符号,只是告诉编译器在执行的时候,去调谁的方法. self是一个隐私参数; self r ...
- 第84讲:Scala中List和ListBuffer设计实现思考
今天来学习了scala中的list和ListBuffer scala list 内部很多操作是listbuffer做的,因为改变元素,listbuffer非常高效,tl是var类型的 ,但是他属于s ...