FreeSql取多表資料
阿新 • • 發佈:2019-12-31
FreeSql取多表資料
以文章隨筆與分類為例。
- 表結構 部分欄位如下,其他省略,為了展示一對多關聯,一個分類下可以有多個文章。一個文章屬於一個分類。
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; }
}
複製程式碼
使用現有的導航屬性
- 屬性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();
複製程式碼
- 同樣是使用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
- 不使用關聯屬性獲取文章專欄,這時候類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"
);
複製程式碼
總結
以上取出的資料行數都是一樣的。
一對多。
- 寫SQL,很簡單。
- 使用ORM的Join,再配合Mapper就變得複雜了。
- 使用導航屬性,取關聯資料,一個InClude就解決問題了
- 使用導航屬性,取關聯資料,然後再配合Mapper,基本就要看你的Linq、AutoMapper的水平了。哈哈。
比如上面把Article類中的Classify中的某一個值取出轉換成ArticleDto中的ClassifyName