1. 程式人生 > 程式設計 >FreeSql取多表資料

FreeSql取多表資料

FreeSql取多表資料

以文章隨筆與分類為例。

  1. 表結構 部分欄位如下,其他省略,為了展示一對多關聯,一個分類下可以有多個文章。一個文章屬於一個分類。

blog_article (隨筆表)

欄位 型別 備註
id int
classify_id int 分類id
title varchar(50) 標題
content varchar(4000) 正文

blog_classify (隨筆分類專欄)

欄位 型別 備註
id int
ClassifyName varchar(50) 分類名

其中FullAduitEntity,Entity,在開源專案中,可以自行搜尋,其中就是ABP中的建立時間、是否刪除等欄位

Article.cs

  [Table(Name = "blog_article")]
    public class Article : FullAduitEntity
    {
        /// <summary>
        /// 文章所在分類專欄Id
        /// </summary>
        public int? ClassifyId { get; set; }

        public Classify Classify { get; set; }
        /// <summary>
        /// 標題
        /// </summary>
        [Column(DbType = "varchar(200)"
)] public string Title { get; set; } /// <summary> /// 正文 /// </summary> [Column(DbType = "text")] public string Content { get; set; } } 複製程式碼

Classify.cs

    [Table(Name = "blog_classify")]
   public class Classify:FullAduitEntity
    {
        public string ClassifyName { get; set
; } public List<Article> Articles { get; set; } } 複製程式碼

使用現有的導航屬性

  1. 屬性Classify為null
List<Article> articles1 = _articleRepository
                        .Select
                        .ToList();
複製程式碼

2.屬性Classify會有值 我們在前臺取資料,也可以直接迴圈取Classify中的屬性

List<Article>articles2=  _articleRepository
    .Select
    .Include(r => r.Classify)
    .ToList();
複製程式碼

假如,後臺有一些欄位要想過濾掉,可使用AutoMapper,傳給前臺使用Dto,過濾建立時間,修改時間等稽核日誌

建立 ArticleDto

   public class ArticleDto : Entity
    {
        /// <summary>
        /// 類別Id
        /// </summary>
        public int? ClassifyId { get; set; }
        /// <summary>
        /// 類別名稱
        /// </summary>        
        public string ClassifyName { get; set; }
        public string Content { get; set; }
        public string Title { get; set; }
    }
複製程式碼

3、配合IMapper,轉換為ArticleDto

List<ArticleDto> articles3 = _articleRepository
            .Select
            .ToList(r=>new
            {
                r.Classify,Article=r
            }).Select(r=>
            {
                ArticleDto articleDto=_mapper.Map<ArticleDto>(r.Article);
                articleDto.ClassifyName = r.Classify.ClassifyName;
                return articleDto;
            }).ToList();
複製程式碼
  1. 同樣是使用IMapper轉換,但這裡Include進去了,用法稍微有點區別。

檔案介紹Include"貪婪載入導航屬性,如果查詢中已經使用了 a.Parent.Parent 類似表示式,則可以無需此操作。。

這裡說的查詢使用了a.Parent.Parent,是指上面的3中,ToList 中的

  .ToList(r=>new
        {
            r.Classify,Article=r
        })
複製程式碼

r.Classify,會生成Join功能。如果不想ToList去選擇需要的資料,可直接使用Include把需要關聯的資料取出。在後面再使用Linq的Select把資料轉換下,後面要注意r.Classify可能為null,需要?.取。因為ClassifyId非必填項。

List<ArticleDto> articles4 = _articleRepository
    .Select
    .Include(r => r.Classify)
    .ToList().Select(r =>
    {
        ArticleDto articleDto = _mapper.Map<ArticleDto>(r);
        articleDto.ClassifyName = r.Classify?.ClassifyName;
        return articleDto;
    }).ToList();

複製程式碼

直接Join

  1. 不使用關聯屬性獲取文章專欄,這時候類Article中的Classify屬性和Classify表中的List<Article>可刪除,
List<ArticleDto> articleDtos = _articleRepository
            .Select
            .From<Classify>((a,b) =>a.LeftJoin(r => r.ClassifyId == b.Id)
            ).ToList((s,a) => new
            {
                Article = s,a.ClassifyName
            })
            .Select(r =>
            {
                ArticleDto articleDto = _mapper.Map<ArticleDto>(r.Article);
                articleDto.ClassifyName = r.ClassifyName;
                return articleDto;
            }).ToList();
複製程式碼

使用SQL直接獲取文章及其分類名稱

6.SQL需要自己增加is_deleted判斷。

List<ArticleDto> t9 = _freeSql.Ado.Query<ArticleDto>($@"
                SELECT a.*,b.item_name as classifyName 
                FROM blog_article a 
                LEFT JOIN base_item b 
                on a.classify_id=b.id where a.is_deleted=0"
);
複製程式碼

總結

以上取出的資料行數都是一樣的。
一對多。

  1. 寫SQL,很簡單。
  2. 使用ORM的Join,再配合Mapper就變得複雜了。
  3. 使用導航屬性,取關聯資料,一個InClude就解決問題了
  4. 使用導航屬性,取關聯資料,然後再配合Mapper,基本就要看你的Linq、AutoMapper的水平了。哈哈。

比如上面把Article類中的Classify中的某一個值取出轉換成ArticleDto中的ClassifyName