文章出處

上一篇, 提到Query<Test>查詢的時候, 如果Test中包含自定義class, Dapper不會給自定義class完成映射, 而是直接給null, 其實是可以實現的, 答案就在下面的基本用法介紹中

 提到用法, 首先是要實現CURD, 這里先介紹Read吧.

先上實體:

    public enum Gender
    { 
        男 = 0,
        女
    }

    public class Tch_Teacher
    {
        public int Id { get; set; }

        public Gender Sex { get; set; }
        
        public string Name { get; set; }

        public bool IsDoublePosition { get; set; }

        public DateTime CreateDate { get; set; }
    }
    public class Tch_Contact
    {
        public int Id { get; set; }

        public int TId { get; set; }

        public string Phone { get; set; }

        public string QQ { get; set; }

        public string Weixin { get; set; }
    }
    public class TeacherInfo
    {
        public Tch_Contact Contact { get; set; }

        public Tch_Teacher Teacher { get; set; }
    }

一、一對一映射

var sql = string.Empty;

sql = "select Count(1) from tch_teacher where id>@Id limit 3;";
Console.WriteLine(conn.Query<int>(sql, new { Id = 10 }));
Console.WriteLine(conn.Query<string>(sql, new { Id = 1 }));

sql = "select Sex, Id, Name, CreateDate, No from tch_teacher limit 3;";
var list = conn.Query<Test>(sql);
var list1 = conn.Query<object>(sql);
var list2 = conn.Query<dynamic>(sql); Console.WriteLine(list.ToList().FirstOrDefault().Name);

一對一映射還是蠻簡單的, 不需要解釋了,  這種寫法, 就是前面提到的, 如果Tch_Teacher里面有一個Tch_Contact類型的屬性, 那么在映射的時候, 這個屬性會直接賦值為null

 

二、一對多映射

sql = @"select a.Id, a.Sex, a.Name, a.CreateDate, a.No, b.Id, b.Phone, b.QQ, 
b.Weixin from tch_teacher a left join tch_contact b on a.Id = b.TId order by a.Id asc limit 3;
"; //No這個字段, 在類中并沒有 var list1 = conn.Query<Test, Tch_Contact, TeacherInfo>(sql, (a, b) => { TeacherInfo tInfo = new TeacherInfo(); if (a != null) { tInfo.Teacher = a; } if (b != null) { tInfo.Contact = b; } return tInfo; }); //}, null, null, true, "Id", null, null);

此時, 返回的 List<TeacherInfo> 中, Teacher 和 Contact 都是有值的, 而不是直接給null, 當然, TeacherInfo中, 還可以有別的字段, 比如 public int No {get;set;},

此時的No是能獲取到值的. 其中的映射原理, 這里我就不再贅述了, 能看懂Dapper中一對一映射的原理, 一對多映射也就差不多了. 

 如果將 TeacherInfo類中Contact屬性修改一下, 改成 List<Tch_Contact>類型, 那么怎樣得到一個按 Tch_Teacher 分組的數據呢?

通常情況下, 會想到兩種辦法:

一種是上面這種辦法, 先得到全部數據, 然后通過GroupBy方法, 進行分組, 也能得到那種分組數據, 但那并不理想, 這種方法我就不貼了.

  1. 得到的數據, 并不是我們想要的那種格式數據, 雖然也是分組的數據.

  2. 有重復項. Tch_Teacher并沒有得到去除重復的功能. 雖然分了組, 但是每組中的數據, Tch_Teacher仍然是重復的.

 另一種, 就是通過一個中間變量來獲取, 方法如下:

sql = @"select a.Id, a.Sex, a.Name, a.CreateDate, a.No, b.Id, b.Phone, b.QQ, b.Weixin 
    from tch_teacher a left join tch_contact b on a.Id = b.TId order by a.Id asc limit 6;"; 
var infos = new Dictionary<int, TeacherInfo>();
var list1 = conn.Query<Test, Tch_Contact, TeacherInfo>(sql, (a, b) =>
{
    TeacherInfo tInfo;
    if (!infos.TryGetValue(a.Id, out tInfo))
    {
        tInfo = new TeacherInfo();
        tInfo.Contact = new List<Tch_Contact>();
        tInfo.Teacher = a;
        infos.Add(a.Id, tInfo);
    }
    if (b != null)
    {
        infos[a.Id].Contact.Add(b);
    }
    return infos[a.Id];
});

使用字典項, 在其中進行一個規整操作, 去除重復的 Tch_Teacher信息, 把Tch_Contact進行規整分組. 而且, 得到的結果, 就直接是想要的結果

public class TeacherInfo
{
    public List<Tch_Contact> Contact { get; set; }

    public Tch_Teacher Teacher { get; set; }
}

 話說回來, 至于最終使用哪種方法, 要根據具體使用需求來定, 總體來說, 都能達到效果. 方法無好壞, 只是使用場景不同. 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()