SQLSugar进阶使用:高级查询与性能优化

news2024/9/24 15:21:18

文章目录

  • 前言
  • 一、高级查询
    • 1.查所有
    • 2.查询总数
    • 3.按条件查询
    • 4.动态OR查询
    • 5.查前几条
    • 6.设置新表名
    • 7.分页查询
    • 8.排序 OrderBy
    • 9.联表查询
    • 10.动态表达式
    • 11.原生 Sql 操作 ,Sql和存储过程
  • 二、性能优化
    • 1.二级缓存
    • 2.批量操作
    • 3.异步操作
    • 4.分表组件,自动分表
    • 5.查询
    • 6.插入
    • 7.删除数据
    • 8.引入库
    • 9.读写分离/主从
  • 总结


前言

    SqlSugar作为一款专为.NET平台设计的轻量级ORM(对象关系映射)框架,其进阶使用中的高级查询与性能优化涵盖了多个方面的内容。


一、高级查询

    SqlSugar提供了丰富的高级查询功能,以满足复杂的业务需求,主要包括:

1.查所有

List<Student> list=db.Queryable<Student>().ToList()
//select * from Student

2.查询总数

int count=db.Queryable<Student>().Count()
//select count(1) from Student

3.按条件查询

db.Queryable<Student>().Where(it=>it.Id==1).ToList()
//select * from Student where id=1
 
db.Queryable<Student>().Where(it=>it.name !=null).ToList()//不是null
//select * from Student where name is not null
 
db.Queryable<Student>().Where(it=>it.name ==null).ToList()//是null
//select * from Student where name is null
 
db.Queryable<Student>().Where(it=>it.name !="").ToList()//不是空 ,不为空
//select * from Student where name <> ''

4.动态OR查询

var exp= Expressionable.Create<Student>();
exp.OrIF(条件,it=>it.Id==1);//.OrIf 是条件成立才会拼接OR
exp.Or(it =>it.Name.Contains("jack"));//拼接OR
var list=db.Queryable<Student>().Where(exp.ToExpression()).ToList();

5.查前几条

db.Queryable<Student>().Take(10).ToList()
//select top 10 * from Student

6.设置新表名

//例1:更新表名
db.Queryable<School>().AS("Student").ToList();
//生成的SQL  SELECT [ID],[NAME] FROM  Student
//动态表名 表别名 指定表明
 
//例2:给表名添加前缀
db.Queryable<School>().AS("dbo.School").ToList();
//生成的SQL  SELECT [ID],[NAME] FROM  dbo.School

7.分页查询

.ToPageList(pagenumber, pageSize)// 不返回Count
.ToPageList(pagenumber, pageSize, ref totalCount)//返回Count
.ToPageList(pagenumber, pageSize, ref totalCount,ref totalPage)//返回Count+总页数

8.排序 OrderBy

var list =db.Queryable<Student>()
.LeftJoin<School>((st, sc) =>st.SchoolId==sc.Id)
.OrderBy((st,sc)=>st.SchoolId)//写Select前面用法,正常都这么用
.Select((st,sc)=>new Dto(){ id=it.id ,Name=it.Name})
.ToList();

9.联表查询

//联表查询
var query5 = db.Queryable<Order>()
         .LeftJoin<Custom>((o,cus) => o.CustomId == cus.Id)//多个条件用&&
         .LeftJoin<OrderDetail> ((o,cus,oritem) => o.Id == oritem.OrderId)
         .Where(o => o.Id == 1)  
         .Select((o,cus,oritem) => new ViewOrder {Id=o.Id,CustomName = cus.Name })
         .ToList();  //ViewOrder是一个新建的类,更多Select用法看下面文档

10.动态表达式

//用例1:连写
Expression<Func<Order, bool>> exp = Expressionable.Create<Order>() //创建表达式
              .AndIF(p > 0, it => it.Id == p)
              .AndIF(name != null, it => it.Name == name && it.Sex==1)
              .ToExpression();//注意 这一句 不能少
               
var list = db.Queryable<Order>().Where(exp).ToList();//直接用就行了不需要判段 null和加true
   
 
//用例2:分开写法
var expable= Expressionable.Create<Order>();
...逻辑
expable.And(it.xx==x);
...逻辑
expable.And(it.yy==y);
...逻辑
var exp=expable.ToExpression();//要用变量 var exp=
db.Queryable<Order>().Where(exp).ToList()//直接用就行了不需要判段 null和加true
 
//用例3:多表查询
var exp=Expressionable.Create<Order,T2,T3>()
         .And((x,y,z)=>z.id==1).ToExpression();//注意 这一句 不能少
          
          
//技巧 WhereIF 有时候更方便
var list=db.Queryable<T>()
.WhereIF(p>0,it=>it.p==p)
.WhereIF(y>0,it=>it.y==y)
.ToList()

11.原生 Sql 操作 ,Sql和存储过程

//调用Sql
db.Ado.具体方法
 
//调用存储过程
db.Ado.UseStoredProcedure().具体方法

    方法列表:
在这里插入图片描述

二、性能优化

    为了提升数据库操作的性能,SqlSugar提供了多种优化措施。

1.二级缓存

    二级缓存是将结果集进行缓存,当SQL和参数没发生变化的时候从缓存里面读取数据,减少数据库的读取操作。

  • 维护方便:SqlSugar的 二级缓存 支持单表和多表的 CRUD 自动缓存更新 ,减少了复杂的缓存KEY维护操作
  • 使用方便:可以直接在Queryable.WithCache直接缓存当前对象
  • 外部集成:通过实现ICacheService接口,来调用外部缓存方法,想用什么实现什么

    注意:Sql语句一直在变的就不适合缓存,比如 ID=?这种SQL都在变化,并且表的数量巨大这种情况就不要使用缓存了,缓存适合加

2.批量操作

    批量操作海量数据操作ORM性能瓶颈在实体转换上面,并且不能使用常规的Sql去实现。
    当列越多转换越慢,SqlSugar将转换性能做到极致,并且采用数据库最佳API,操作数据库达到极限性能。

    1.BulkCopy
    大数据插入

db.Fastest<Order>().BulkCopy(lstData);//插入
db.Fastest<Order>().PageSize(100000).BulkCopy(insertObjs);
db.Fastest<System.Data.DataTable>().AS("order").BulkCopy(dataTable);

    2.BulkUpdate
    大数据更新

db.Fastest<Order>().BulkUpdate(GetList())//更新
db.Fastest<Order>().PageSize(100000).BulkUpdate(GetList())//更新
db.Fastest<Order>().BulkUpdate(GetList(),new string[] { "Id"});//无主键
db.Fastest<Order>().BulkUpdate(GetList(), new string[]{"id"},
                     new string[]{"name","time"})//只更新几列
//DataTable                           
db.Fastest<System.Data.DataTable>().AS("Order").BulkUpdate(dataTable,new string[] {"Id"});//Id是主键
db.Fastest<System.Data.DataTable>().AS("Order").BulkUpdate(dataTable,new string[] {"Id"},更新的列);

    3. BulkMerge (5.1.4.109)
    大数据 :插入或者更新

//原理
//Oracle和SqlServer使用了Merge Into+BulkCopy
//其他库底层是 db.Storageable(list).ExecuteSqlBulkCopy()
 
db.Fastest<Order>().BulkMerge(List);
db.Fastest<Order>().PageSize(100000).BulkMerge(List);
 
//DataTable 升级到:SqlSugarCore 5.1.4.147-preview15+
db.Fastest<System.Data.DataTable>()
        .AS("Order")//表名
        //第一个参数datatable
        //第二个参数主键
        //第三个参数是不是自增 true为自增
       .BulkMerge(dt, new string[] { "Id" },true);

    4. BulkQuery
    普通查询就行了性能超快

db.Queryable<Order>().ToList();//比Dapper略快
 
//分页降低内存 适合复杂的DTO转换和导出
List<Order> order = new List<Order>(); 
db.Queryable<Order>().ForEach(it=> { order.Add(it); /*禁止这儿操作数据库因为会循环*/} ,2000);

    5. BulkDelete
    直接用分页删除就行了

db.Deleteable<Order>(list).PageSize(1000).ExecuteCommand();

3.异步操作

    释放主线程的占用,提高吞吐量,直接运行并不能提高速度,合适场景使用,当然全部都写异步也并没大问题,只是代码难提升了,建议合适场景使用,高并发,数据库请求时间过长等场景使用。
    SqlSugar中ToList是同步方法,那么ToListAsync这种是异步方法,通过Async来区别是同步还是异步方法。

var data=await db.Queryable<Order>().FirstAsync();
var list= await db.Queryable<Order>().Where(it=>it.Id==1).ToListAsync();
  
//分页需要特别注意用法
RefAsync<int> total = 0;
var list=await Db.Queryable<Order>().ToPageListAsync(1, 2, total);

4.分表组件,自动分表

    自带分表支持按年、按季、按月、按周、按日进行分表(支持混合使用)。

  • 可扩展架构设计,比如一个ERP用5年不卡,到了10就卡了,很多人都是备份然后清空数据
  • 数据量太多 ,例如每天都有 几十上百万的数据进入库,如果不分表后面查询将会非常缓慢
  • 性能瓶颈 ,数据库现有数据超过1个亿,很多情况下索引会莫名失效,性能大大下降

    1.定义实体:
    我们定义一个实体,主键不能用自增或者int ,设为long或者guid都可以,我例子就用自带的雪花ID实现分表。

[SplitTable(SplitType.Year)]//按年分表 (自带分表支持 年、季、月、周、日)
[SugarTable("SplitTestTable_{year}{month}{day}")]//3个变量必须要有,这么设计为了兼容开始按年,后面改成按月、按日
 public class SplitTestTable
 {
     [SugarColumn(IsPrimaryKey =true)]
     public long Id { get; set; }
  
     public string Name { get; set; }
      
     [SugarColumn(IsNullable = true)]//设置为可空字段 (更多用法看文档 迁移)
     public DateTime UpdateTime{get;set;}
      
     [SplitField] //分表字段 在插入的时候会根据这个字段插入哪个表,在更新删除的时候用这个字段找出相关表
     public DateTime CreateTime { get; set; }
 } 
  
 //按年分表格式如下
 SplitTestTable_20220101
  
 //比如现在5月按月分表格式如下
 SplitTestTable_20220501
  
 //比如现在5月11日按日分表格式如下
 SplitTestTable_20220511

    2.同步表和结构
    假如分了20张表,实体类发生变更,那么 20张表可以自动同步结构,与实体一致。

//不写这行代码 你也可以用插入建表,插入用法看文档下面
db.CodeFirst
    .SplitTables()//标识分表
     .InitTables<SplitTestTable>(); //程序启动时加这一行,如果一张表没有会初始化一张

    注意:插入会自动建表不需要这行代码,主要用于实体改动后同步多个表结构,或者一张表没有初始一张,禁止写到业务里面多次执行。

5.查询

    1.查询: 时间过滤
    通过开始时间和结束时间自动生成CreateTime的过滤并且找到对应时间的表。

//简单示例
var list=db.Queryable<OrderSpliteTest>().SplitTable(beginDate,endDate).ToPageList(1,2); 
 
//结合Where
var list=db.Queryable<OrderSpliteTest>().Where(it=>it.Id>0).SplitTable(beginDate,endDate).ToPageList(1,2); 
 
//注意:
//1、 分页有 OrderBy写 SplitTable 后面 ,uinon all后在排序
//2、 Where尽量写到 SplitTable 前面,先过滤在union all 
//原理:(sql union sql2) 写SplitTable 后面生成的括号外面,写前生成的在括号里面

    2. 查询: 选择最近的表
    如果下面是按年分表 Take(3) 表示 只查 最近3年的分表数据。

var list=db.Queryable<OrderSpliteTest>()

            .Where(it=>it.Pk==Guid.NewGuid())

            .SplitTable(tabs => tabs.Take(3))//近3张,也可以表达式选择

            .ToList();

    3.查询: 精准定位一张表
    根据分表字段的值可以精准的定位到具体是哪一个分表,比Take(N)性能要高出很多

var name=Db.SplitHelper<SplitTestTable>().GetTableName(data.CreateTime);//根据时间获取表名
 
//推荐:表不存在不会报错
var list=db.Queryable<OrderSpliteTest>().SplitTable(tabs => tabs.InTableNames(name)).ToList()
 
//不推荐:查询不推荐用,删除和更新可以用
var list=Db.Queryable<SplitTestTable>().AS(name).Where(it => it.Id==data.Id).ToList();

    4.查询: 表达式定位哪几张表

Db.Queryable<SplitTestTable>()
          .Where(it => it.Id==data.Id)
          .SplitTable(tas => tas.Where(y=>y.TableName.Contains("2019")))//表名包含2019的表
          .ToList();

    5.查询: 分表Join正常表

//分表使用联表查询
var list=db.Queryable<Order>() // Order是分表
.SplitTable(tabs=>tabs.Take(3)) //可以换成1-8的所有分表写法,不是只能take
.LeftJoin<Custom>((o,c)=>o.CustomId==c.Id)//Custom正常表
.Select((o,c)=>new { name=o.Name,cname=c.Name }).ToPageList(1,2); 

    6.查询: 分表JOIN分表

var rightQuery=db.Queryable<Custom>().SplitTable(tabs=>tabs.Take(3)) ;
var list=db.Queryable<Order>().SplitTable(tabs=>tabs.Take(3)) 
.LeftJoin<Custom>(rightQuery,(o,c)=>o.CustomId==c.Id) // Join  rightQuery
.Select((o,c)=>new { name=o.Name,cname=c.Name }).ToPageList(1,2); 
 
 
//技巧:如果是单表分表没有表返回第一个表可以防止报错  升级到:5.1.4.127 +
SplitTable(it=>it.ContainsTableNamesIfNullDefaultFirst("table"))

    7. 查询: 性能优化
    条件尽可能写在SplitTable前面,因为这样会先过滤在合并

.Where(it => it.Pk == Guid.NewGuid()) //先过滤
.SplitTable(tabs => tabs.Take(3))//在分表

    8.查询: 所有分表检索

//如果是主键查询哪怕100个分表都很快 
var list = db.Queryable<OrderSpliteTest>()
         .Where(it => it.Pk == Guid.NewGuid()) //适合有索引列,单条或者少量数据查询
         .SplitTable().ToList();//没有条件就是全部表
           
//老版本
var list = db.Queryable<OrderSpliteTest>()
         .Where(it => it.Pk == Guid.NewGuid()) //适合有索引列,单条或者少量数据查询
          .SplitTable(tab=>tab).ToList();

6.插入

    因为我们用的是Long所以采用雪花ID插入(guid也可以禁止使用自增列)

var data = new SplitTestTable()
{
      CreateTime=Convert.ToDateTime("2019-12-1"),//要配置分表字段通过分表字段建表
      Name="jack"
 };
 //雪花ID+表不存在会建表
 db.Insertable(data).SplitTable().ExecuteReturnSnowflakeIdList();//插入并返回雪花ID并且自动赋值ID   
  //服务器时间修改、不同端口用同一个代码、多个程序插入一个表都需要用到WorkId
  //保证WorkId唯一 ,程序启动时配置 SnowFlakeSingle.WorkId=从配置文件读取;
  
  
 //GUID+表不存在会建表
  db.Insertable(data).SplitTable().ExecuteCommand();//插入GUID 自动赋值 ID
   
 //大数据写入+表不存在会建表
 db.Fastest<OrderSpliteTest>().SplitTable().BulkCopy(List<OrderSpliteTest>);//自动找表大数据写入
  
 //不会自动建表 如果表100%存在用这个性能好些
 db.Fastest<OrderSpliteTest>().AS(表名).BulkCopy(List<OrderSpliteTest>);//固定表大数据写入

    注意:.SplitTable不要漏掉了

7.删除数据

    1.推荐用法:新功能 5.0.7.7 preview及以上版本

//直接根据实体集合删除 (全自动 找表插入)
 db.Deleteable(deleteList).SplitTable().ExecuteCommand();//,SplitTable不能少

    2.最近3张表都执行一遍删除

db.Deleteable<SplitTestTable>().In(id).SplitTable(tas=>tas.Take(3)).ExecuteCommand();

    3.精准删除
    相对于上面的操作性能更高,可以精准找到具体表

var tableName=Db.SplitHelper<SplitTestTable>().GetTableName(data.CreateTime);//根据时间获取表名
db.Deleteable<SplitTestTable>().AS(tableName).Where(deldata).ExecuteCommand();
 //DELETE FROM [SplitTestTable_20210101] WHERE [Id] IN (1454676863531089920)

    4.范围删除

var tables = db.SplitHelper<OrderSpliteTest>().GetTables().Take(3);//近3张分表
foreach (var item in tables)
{
   //删除1点到6点时间内数据
   db.Deleteable<OrderSpliteTest>() .AS(item.TableName)//使用当前分表名
                     .Where(it => it.Time.Hour < 1&&it.Time.Hour<6)
                    .ExecuteCommand();
}

8.引入库

    推荐用法: 新功能 5.0.7.7 preview及以上版本

//直接根据实体集合更新 (全自动 找表更新)
db.Updateable(updateList).SplitTable().ExecuteCommand();//.SplitTable()不能少
 
//BulkCopy分表更新
db.Fastest<OrderSpliteTest>().SplitTable().BulkUpdate(List<OrderSpliteTest>);
//部分数据库需配置 具体用法看文档:
 
 
//范围更新
var tables = db.SplitHelper<OrderSpliteTest>().GetTables().Take(3);//近3张分表
foreach (var item in tables)
{
   //更新1点到6点时间内数据
   db.Updateable<OrderSpliteTest>() .AS(item.TableName)//使用分表名
                    .SetColumns(it=>new OrderSpliteTest(){ Static=1 })
                    .Where(it => it.Time.Hour < 1&&it.Time.Hour<6)
                    .ExecuteCommand();
}

    更多用法:

//更新近3张表
db.Updateable(deldata).SplitTable(tas=>tas.Take(3)).ExecuteCommand();
 
//精准找单个表
var tableName=Db.SplitHelper<SplitTestTable>().GetTableName(data.CreateTime);//根据时间获取表名
db.Updateable(deldata).AS(tableName).ExecuteCommand();//实体
db.Updateable<TestEnity>().AS(tableName).SetColumns(..).Where(...).ExecuteCommand();//表达式
 
//通过表达式过滤出要更新的表
db.Updateable(deldata).SplitTable(tas => tas.Where(y=>y.TableName.Contains("_2019"))).ExecuteCommand();

9.读写分离/主从

    1.配置从表

  • 如果存在事务所有操作都走主库,不存在事务 修改、写入、删除走主库,查询操作走从库
  • HitRate 越大走这个从库的概率越大
    假设A从库 HitRate设置为5,假设B从库 HitRate设置为10,A的概率为33.3% B的概率为66.6%
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
                ConnectionString = Config.ConnectionString,//主库
                DbType = DbType.SqlServer,
                IsAutoCloseConnection = true,
                //从库
                SlaveConnectionConfigs = new List<SlaveConnectionConfig>() {
                     new SlaveConnectionConfig() { HitRate=10, ConnectionString=Config.ConnectionString2 } ,
                     new SlaveConnectionConfig() { HitRate=10, ConnectionString=Config.ConnectionString2 }
                }
 });

    2.强制走主库

    新功能:5.0.8 用法和Queryable一样

Db.MasterQueryable<T>().Where(x=>x.id==1).ToList() //强制走主库
//5.1.3.22修复了异步不会生效

    事务

//事务中全部会走主库

    通过配置走主库

//方式1.强制配置
db.Ado.IsDisableMasterSlaveSeparation=true

总结

    综上所述,SqlSugar的高级查询功能提供了强大的数据筛选、排序和连表查询能力,而性能优化则通过缓存、SQL优化、批量操作等多种手段来提高数据库操作的效率。这些特性使得SqlSugar在.NET开发领域具有广泛的应用前景。

“笑对人生,智慧同行!博客新文出炉,微信订阅号更新更实时,等你笑纳~”
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2074084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

了解Redis数据持久化(上)

Redis常用作缓存&#xff0c;提高读取相应性能。Redis如果宕机可以从后端数据库里恢复数据&#xff0c;但是会出现的问题&#xff1a; 数据是从慢速数据库里获取数据&#xff0c;速度比不上从Redis缓存中获取。频繁访问数据库会给数据库造成压力。 处理宕机的方法就是&#xf…

Go 调用Rust函数

Go 调用Rust函数 在golang 中,go可以引用c代码&#xff0c;和c共舞&#xff0c;也就是cgo.在一些包里就能看到cgo的身影&#xff0c;gopcap(引用了libpcap),go-sqlite(引用了libsqlite).毕竟c是"万物之主"嘛.本文利用cgo实现go调rust函数 这是一个rust demo用于生成…

【Docker】Docker学习03 | Docker的volume

本文首发于 ❄️慕雪的寒舍 1. 引入 在docker的基本知识讲解中&#xff0c;提到了docker镜像是由一层一层文件系统构成的。这一系列文件系统是一系列的只读层。当我们创建一个容器的时候&#xff0c;Docker会读取镜像&#xff08;只读&#xff09;&#xff0c;并在镜像的顶部再…

SpringBoot集成google登陆快速入门Demo

1.为何要使用 Google 账号登录 借助“使用 Google 账号登录”功能&#xff0c;您可通过安全性备受信赖的 Google 账号&#xff0c;轻松快捷地在网上登录和注册网站与应用。该功能可消除您对密码的依赖&#xff0c;从而降低使用密码带来的困扰和安全风险。 2.环境准备 登录 G…

【IEEE出版】第八届电气、机械与计算机工程国际学术会议(ICEMCE 2024,10月25-27)

由西京学院主办&#xff0c;AEIC学术交流中心协办&#xff0c;中国科学技术大学、深圳大学、浙江工业大学等校联合支持的第八届电气、机械与计算机工程国际学术会议&#xff08;ICEMCE 2024&#xff09;将于2024年10月25日至27日在西安举办。 本次会议主要围绕“电气”、"…

【文档】软件项目售后服务标准文档参考(word原件)

软件售后服务方案的售后服务范围广泛&#xff0c;涵盖了多个方面&#xff0c;以确保客户在使用软件过程中得到全面、及时的支持。具体来说&#xff0c;这些服务范围通常包括以下几个核心内容&#xff1a; 技术支持服务维护与更新服务培训与教育服务定制化服务数据管理与服务客户…

[C语言]一、C语言基础(函数)

G:\Cpp\C语言精讲 6. 函数 6.1函数的基本使用 6.1.1 为什么需要函数 《街霸》游戏中&#xff0c;每次人物出拳、出脚或跳跃等动作都需要编写50-80行的代码&#xff0c;在每次出拳、出脚或跳跃的地方都需要重复地编写这50-80行代码&#xff0c;这样程序会变得很臃肿&#xff…

[学习笔记]深度学习详解-Datawhale学习组

第三章&#xff1a;深度学习基础 3.1 局部极小值与鞍点 3.1.1 临界点及其种类 优化神经网络时&#xff0c;使用梯度下降法&#xff0c;遇到梯度为0的点&#xff0c;训练就停了下来&#xff0c;损失也不再下降。 这个梯度为0的点&#xff0c;可以称为临界点。 临界点可以细分…

在挫折感中遇见更好的自己

你是如何克服编程学习中的挫折感的&#xff1f; 编程学习之路上&#xff0c;挫折感就像一道道难以逾越的高墙&#xff0c;让许多人望而却步。然而&#xff0c;真正的编程高手都曾在这条路上跌倒过、迷茫过&#xff0c;却最终找到了突破的方法。你是如何在Bug的迷宫中找到出口的…

ssrf+redisssrf+fastcgi

curl支持很多协议&#xff0c;有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDA ssrfredis dict被禁用了用&#xff08;?urlhttp://172.19.0.3端口&#xff09;来探测一下端口吧 172.19.0.3主机只开放一个80端口 看看内网还有其他服务器没 这里可以看到内网还有…

Ai+若依(代码生成 -- 树表“有层级关系的”):【03篇】

代码生成 代码生成器,根据数据库表结构自动生成前后端CRUD代码提供三种生成模板:单表、树表、主子表(一对多)现在来说说树表,主子表 树表: 例如:公司==》部门==》员工 层级关系的这种 主子表: 例如: 数据之间存在一对多,比如菜品和口味表 一个菜品可以多个口味 自动化…

图形几何算法 -- 判断两条线段是否相交

线段相交检测是计算几何中的一个基本问题&#xff0c;广泛应用于计算机图形学、游戏开发、物理模拟等领域。我们可以通过以下步骤和理论来判断两条线段是否相交。 概念 在二维平面上&#xff0c;给定两条线段 A(P1, P2) 和 B(Q1, Q2)&#xff0c;我们需要判断这两条线段是否相…

鸿蒙内核源码分析(双向链表) | 谁是内核最重要结构体?

答案一定是: LOS_DL_LIST(双向链表)&#xff0c;它长这样. typedef struct LOS_DL_LIST {//双向链表&#xff0c;内核最重要结构体struct LOS_DL_LIST *pstPrev; /**< Current nodes pointer to the previous node *///前驱节点(左手)struct LOS_DL_LIST *pstNext; /**<…

Linux-部署YUM仓库及NFS共享服务

系列文章目录 提示&#xff1a;仅用于个人学习&#xff0c;进行查漏补缺使用。 1.Linux-网络设置 2.Linux-DHCP服务、vsftp 3.Linux-DNS域名解析服务 4.Linux-远程访问及控制 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档…

【GIS系列】多源异构原始影像解析:策略模式与规则引擎的应用

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 1. 前言 在遥感技术和地球观测领域&#…

机器学习周报(8.19-8.25

文章目录 摘要Abstract1.PyTorch环境的配置及安装使用PyCharm配置环境安装配置jupyter 2.两个Python常用函数3.DataSet4.TensorBoard的使用绘制一幅坐标图使用tendorboard对一幅图片进行操作 5.torchvison中的transforms总结 摘要 在之前学习了一些机器学习相关理论之后&#…

【限时免费发放】2000+热门Scratch作品源码

欢迎访问小虎鲸Scratch资源站&#xff01;在Scratch编程的学习过程中&#xff0c;优质的资源和灵感是至关重要的。因此&#xff0c;我们特别准备了这份【免费下载】的Scratch作品源码合集&#xff0c;包含超过2000个精选的Scratch项目源码&#xff0c;旨在为Scratch编程爱好者和…

Nginx+keepalived实现高可用

目录 一、准备工作 1、安装软件 二、配置master主服务器 1、修改nginx主配置文件 ​编辑 2、修改keepalived主配置文件 三、配置backup备服务器 四、配置节点服务器 1、配置第一个节点服务器 1.1、设置虚拟网卡 1.2、忽略ARP请求 1.3、安装并启动nginx软件 2、配置…

【STM32】SPI接口(非连续传输)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 前言 SPI简介 IO口初始化 SPI配置 时钟使能 SPI初始化 SPI使能 数据接收与发送 硬件SPI代码 MySPI.h MySPI.c 前言 【通信协议】SPI总线-CSDN博客 本篇博客学习使用STM32的…

Expo 开发ReactNative 后切换 eas 账号

修改slug app.json中的sulg字段更新为新账号应用sulg 修改projectId app.json中的extra.eas.projectId字段更新为新账号应用projectId 退出账号&#xff1a; eas logout 重新登录&#xff1a; eas login