zoukankan      html  css  js  c++  java
  • FreeSql 新功能介绍:贪婪加载五种方法

    前言

    FreeSql 在经过6个月的开发和朋友们的工作实践,不断的改进创新,目前拥有1500个左右单元测试方法,且每个方法内又复盖不同的测试面。

    今天介绍 FreeSql 各种贪婪加载的姿势,作下总结。本节内容对应的还有【延时加载】,贪婪加载和他本该在一起介绍,开发项目的过程中应该双管齐下,才能写出高质量的程序。有关延时加载,日后有空再单独编写。

    FreeSql是一个功能强大的NETStandard库,用于对象关系映射程序(O/RM),便于开发人员能够使用 .NETStandard 对象来处理数据库,不必经常编写大部分数据访问代码。

    • [√] 支持 CodeFirst 迁移;
    • [√] 支持 DbFirst 从数据库导入实体类,支持三种模板生成器;
    • [√] 采用 ExpressionTree 高性能读取数据;
    • [√] 支持深入的类型映射,比如pgsql的数组类型,堪称匠心制作;
    • [√] 支持丰富的表达式函数;
    • [√] 支持导航属性查询,和延时加载;
    • [√] 支持同步/异步数据库操作方法,丰富多彩的链式查询方法;
    • [√] 支持读写分离、分表分库,租户设计;
    • [√] 支持多种数据库,MySql/SqlServer/PostgreSQL/Oracle/Sqlite;

    贪婪方法一:Dto 映射查询

    Select<Tag>().Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title });
    Select<Tag>().Limit(10).ToList(a => new TestDto());
    Select<Tag>().Limit(10).ToList(a => new TestDto { });
    Select<Tag>().Limit(10).ToList(a => new TestDto() { });
    Select<Tag>().Limit(10).ToList<TestDto>();
    

    像这种映射支持单表/多表。

    查找规则,查找属性名,会循环内部对象 _tables(join 查询后会增长),以 主表优先查,直到查到相同的字段。

    如:

    A, B, C 都有 id,Dto { id, a1, a2, b1, b2 },A.id 被映射。也可以指定 id = C.id 映射。

    还可以在 dto 可以直接映射一个导航属性。

    对头,通过映射某对象,也可以实现贪婪加载,这个功能是在数据库查询前映射的,而不是查回所有数据再重组。

    贪婪方法二:导航属性 ManyToOne/OneToOne

    ManyToOne/OneToOne 导航属性通过 ToList() 加载,这个方法有一个参数:includeNestedMembers。

    参数说明:

    false: 返回 2级 Join 的数据;

    true: 返回所有层级深度 Join 的导航数据;

    如果查询中已经使用了 a.Parent.Parent 类似表达式,则可以无需 LeftJoin 等操作。

    如:

    class Tag {
        [Column(IsIdentity = true)]
        public int Id { get; set; }
        public string Name { get; set; }
    
        public int? Parent_id { get; set; }
        public virtual Tag Parent { get; set; }
    }
    
    Select<Tag>().Where(a => a.Parent.Name == "1").ToList();
    //这样写,不需要再标记 Join,解析表达式时自动处理成 LeftJoin
    

    如果导航属性没有使用,又想加载,可使用 Include 方法。(不好理解可跳过,也许只能在使用中体会)

    Select<Tag>().Include(a => a.Parent).ToList();
    

    贪婪方法三:导航属性 ManyToMany

    IncludeMany 贪婪加载集合的导航属性,其实是分两次查询,在 ToList 后进行了数据重装。

    class Song {
        [Column(IsIdentity = true)]
        public int Id { get; set; }
        public string Title { get; set; }
    
        public virtual ICollection<Tag> Tags { get; set; }
    }
    class Song_tag {
        public int Song_id { get; set; }
        public virtual Song Song { get; set; }
    
        public int Tag_id { get; set; }
        public virtual Tag Tag { get; set; }
    }
    
    Select<Tag>().IncludeMany(a => a.Songs).ToList();
    //这是 ManyToMany 关系的贪婪加载
    

    IncludeMany 有第二个参数,可以进行第二次查询前的修饰工作。

    Select<Tag>().IncludeMany(a => a.Songs, 
        then => then.Where(song => song.User == "admin")).ToList();
    

    然后,其实在 then 那里,还可以继续进行向下 Include/IncludeMany。只要你喜欢,向下 100 层都没问题。

    贪婪方法四:导航属性 OneToMany

    大体与 ManyToMany 用法相同,只是它没有通过中间表查询数据。

    贪婪方法五:变异属性 OneToMany

    变异的 IncludeMany,即使选择的不是导航属性,也可以贪婪加载。适合一些些老项目,导航属性配置不规则的,也可以一对多贪婪加载。

    为了方便理解,我创建了下面两个类,他们没有配置导航关系。你可能会问为啥不配置?我这样是为了直观理解、这样是为了直观理解、这样是为了直观理解!!

    class Order {
        public Guid id { get; set; }
        public string xxx { get; set; }
    
        public List<OrderDetail> Details { get; set; }
    }
    class OrderDetail{
        public Guid id { get; set; }
        public string detailTestField { get; set; }
    
        public Guid OrderId { get; set; }
    }
    
    Select<Order>().IncludeMany(a => a.Details.Where(b => b.OrderId == a.Id)).ToList();
    

    OK,这样查询 order 时,会把 details 也查询回来。

    完结

    我们有考虑在 then 那里实现 limit(5) 功能,场景是只查询每个子记录的前5条回来(待实现)。

    开源地址:https://github.com/2881099/FreeSql

    感谢一直支持的朋友们!

  • 相关阅读:
    Generate Parentheses
    Length of Last Word
    Maximum Subarray
    Count and Say
    二分搜索算法
    Search Insert Position
    Implement strStr()
    Remove Element
    Remove Duplicates from Sorted Array
    Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/kellynic/p/10873837.html
Copyright © 2011-2022 走看看