领域对象: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实现一对多对象关系聚合导航属性的更多相关文章

  1. 关系与导航属性(摘自微软MSDN)

    关系与导航属性 本主题概述实体框架如何管理实体间的关系.还对如何映射和操作关系提供了一些指南. 关系.导航属性和外键 在关系数据库中,表之间的关系(也称为关联)是通过外键定义的.外键 (FK) 是用于 ...

  2. Hibernate单向一对多对象关系模型映射

    1 hibernate 的对象关系映射 Orm: 类-----表 属性------字段 对象------记录 表:在数据库中存在主外键的关系,反向工厂类是由表生成,在由表生成类的时候,类和类之间存在者 ...

  3. Hibernate双向一对多对象关系模型映射

    双向one-to-many 描述部门和岗位:一个部门有多个岗位 将单向的one-to-many 和many-to-one合并. 4.1双向的one-to-many数据库模型 create table ...

  4. FreeSql (十八)导航属性

    导航属性是 FreeSql 的特色功能之一,可通过约定配置.或自定义配置对象间的关系. 导航属性有 OneToMany, ManyToOne, ManyToMany, OneToOne, Parent ...

  5. MVC3+EF4.1学习系列(五)----- EF查找导航属性的几种方式

    文章索引和简介 通过上一篇的学习 我们把demo的各种关系终于搭建里起来 以及处理好了如何映射到数据库等问题 但是 只是搭建好了关系 问题还远没有解决 这篇就来写如何查找导航属性 和查找导航属性的几种 ...

  6. FreeSql 导航属性的联级保存功能

    写在前面 FreeSql 一个款 .net 平台下支持 .net framework 4.5+..net core 2.1+ 的开源 ORM.单元测试超过3100+,正在不断吸引新的开发者,生命不息开 ...

  7. MyBatis加强(1)~myBatis对象关系映射(多对一关系、一对多关系)、延迟/懒加载

    一.myBatis对象关系映射(多对一关系.一对多关系) 1.多对一关系: ---例子:多个员工同属于一个部门. (1)myBatis发送 额外SQL: ■ 案例:员工表通过 dept_id 关联 部 ...

  8. [LINQ2Dapper]最完整Dapper To Linq框架(八)---导航属性

    目录 [LINQ2Dapper]最完整Dapper To Linq框架(一)---基础查询 [LINQ2Dapper]最完整Dapper To Linq框架(二)---动态化查询 [LINQ2Dapp ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (27) ------ 第五章 加载实体和导航属性之关联实体过滤、排序、执行聚合操作

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-9  关联实体过滤和排序 问题 你有一实体的实例,你想加载应用了过滤和排序的相关 ...

随机推荐

  1. Java利用递归实现扫雷

    package 扫雷; import java.math.*; import java.util.Scanner; public class 扫雷 { //记录翻开次数 static int k=0; ...

  2. Mathematics | Mean, Variance and Standard Deviation

    Mean is average of a given set of data. Let us consider below example These eight data points have t ...

  3. matlab 设定坐标比例

    figure() u=-0.1:0.005:0.1; v=-0.1:0.005:0.1; [x,y]=meshgrid(u,v); z=sin(x-y)./abs(x)+abs(y); surf(x, ...

  4. TCP/IP协议(1):各层协议帧格式

    一. 1.OSI与TCP/IP对应: TCP/IP各层功能: 链路层:包括操作系统的设备驱动程序和计算机的网卡,提供底层传输服务.   网络层:为数据选择路由,在众多计算机和网络设备组成的网络中选择一 ...

  5. linux命令tee用法

    功能说明:读取标准输入的数据,并将其内容输出成文件. 语 法:tee [-ai][--help][--version][文件…] 补充说明:tee指令会从标准输入设备读取数据,将其内容输出到标准输出设 ...

  6. 程序员面试50题—sizeof的用法(6)

    以下为Windows下的32 位C++程序,请计算sizeof 的值void Func ( char str[100] ){sizeof( str ) = ?}void *p = malloc( 10 ...

  7. maven打包某个分支的包

    maven打某个分支的包命令: mvn clean install -Dmaven.test.skip=true -Pdevelop

  8. iframe父子元素获取

    jquery.js调用iframe父窗口与子窗口元素的方法 1. jquery在iframe子页面获取父页面元素代码如下: $("#objid",parent.document) ...

  9. MongoDB-环境搭建

    1.下载并安装MongoDB服务 下载地址:mongodb-win32-x86_64-2008plus-ssl-3.2.8-signed 可直接运行mongod命令启动MongoDB服务器,也可以将M ...

  10. 添加wifi adb

    https://blog.csdn.net/ouyang_peng/article/details/50370786 首先弄懂怎么设置adb wifi无线调试的功能,如下所示. 1. 手机端开启adb ...