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");
  • 相关阅读:
    valueOf与toString
    责任链模式
    Js中Symbol对象
    Vue路由懒加载
    updatedb命令
    策略模式
    Docker(3)- Centos 7.x 下 Docker 镜像加速配置
    Vmware
    Docker(2)- Centos 7.x 下安装 Docker
    Docker(1)- 什么是 Docker
  • 原文地址:https://www.cnblogs.com/felixnet/p/7365667.html
Copyright © 2011-2022 走看看