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 Rooms { get; set; }

    public Game()
    {
        this.Rooms = new HashSet();
    }

    public void SetRooms(IEnumerable 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() 或 QueryAsync() 是可以实现,但是去除重复记录比较麻烦。

所以我们扩展两个Query/QueryAsync方法:

/// 
/// 查询带聚合导航属性的对象集合
/// 
/// 主体对象类型
/// 聚合导航对象类型
/// 设置聚合导航属性的方法
public static IEnumerable Query(this IDbConnection cnn, string sql, Action setting, object param = null, string splitOn = "Id")
    where TFirst : class, IEntity<int>
    where TSecond : class, IEntity<int>
{
    TFirst lookup = null;
    var hashes = new HashSet();
    cnn.Query(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;
}

/// 
/// 异步查询带聚合导航属性的对象集合
/// 
/// 主体对象类型
/// 聚合导航对象类型
/// 设置聚合导航属性的方法
public static async Task> QueryAsync(this IDbConnection cnn, string sql, Action setting, object param = null, string splitOn = "Id")
    where TFirst : class, IEntity<int>
    where TSecond : class, IEntity<int>
{
    TFirst lookup = null;
    var hashes = new HashSet();
    await cnn.QueryAsync(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("SELECT * FROM game g LEFT JOIN room r ON r.gameid = g.id", (game, room) =>
{
    game.SetRooms(new HashSet { room });
}, splitOn: "Id");

 

转载于:https://www.cnblogs.com/felixnet/p/7365667.html

你可能感兴趣的:(Dapper实现一对多对象关系聚合导航属性)