zoukankan      html  css  js  c++  java
  • 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 > 0 && 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 > 0 && 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");
  • 相关阅读:
    React Native移动框架功能研究
    移动app框架inoic功能研究
    使用Ivy管理项目中的依赖
    使用Ant自动化我们的java项目生成
    Java构建工具Ant小记(一)
    打造Ubuntu下Java开发环境
    解决系统系统管理员不允许使用保存的凭据登录远程计算机
    Ubuntu全新安装firefox最新版本
    jQuery Ready 与 Window onload 的区别(转)
    程序员的素养
  • 原文地址:https://www.cnblogs.com/felixnet/p/7365667.html
Copyright © 2011-2022 走看看