Dapper实现一对多对象关系聚合导航属性_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > Dapper实现一对多对象关系聚合导航属性

Dapper实现一对多对象关系聚合导航属性

 2017/8/15 17:31:21  felixnet  程序员俱乐部  我要评论(0)
  • 摘要:领域对象:Game(游戏),Room(游戏群),两者一对多的关系,SQL语句中会用到JOINpublicclassGame:AggregateRoot{publicstringTag{get;set;}publicstringTitle{get;set;}publicstringDescription{get;set;}publicIEnumerable<Room>Rooms{get;set;}publicGame(){this.Rooms=newHashSet<
  • 标签:实现 关系 APP

领域对象: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");

 

发表评论
用户名: 匿名