• 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

  • 相关阅读:
    Android笔记(六十六) android中的动画——XML文件定义属性动画
    Android笔记(六十五) android中的动画——属性动画(propertyanimation)
    python函数参数默认值及重要警告
    Python 列表
    Python数学运算入门把Python当作计算器
    Python 的非正式介绍
    python中为什么 if/while/def/class语句需要冒号?
    为什么Python在列表和元组的末尾允许使用逗号?
    现实世界中的 Python
    Python常见问题
  • 原文地址:https://www.cnblogs.com/igeekfan/p/11661506.html
Copyright © 2020-2023  润新知