.NET Core 之 七 EF Core(五)

一、EF Core执行非查询原生sql语句

                为什么要写原生sql语句

                执行非查询sql语句

                        内插值语法:$"我是{name},我的年龄是{age}"

                        多行@

                ctx.Database.ExecateSqlInterpolatedAsync($"inster into...")

                有sql注入漏洞吗? 没有                sql注入最好的解决方案是参数化sql处理

                        1、字符串内插值的方式不会有sql注入攻击漏洞;

                        2、字符串内插如果赋值给string变量,就是字符串拼接;字符串内插值如果赋值给FormattableString类型变量,编译器就会构造FormattableString对象,属性Formar和GetArguments()方法

                        3、ExecuteSqlInterPolatedAsync()的参数FormattableString类型,因此ExecutSqlInterPolatedAsync会进行参数化sql处理

                        4、除了ExecuteSqlInterPolated(),ExecuteSqlInterPolatedAsync()还有ExecuteSqlRaw(),ExecuSqlRawAsync()也可以执行原生sql语句,但需要开发人员自己处理查询参数,用不好容易造成sql注入风险,以前旧版本用,新版本推荐用内插值方法。

二、执行实体相关查询原生sql语句

        如果要执行的原生sql是一个查询语句,并且查询结果也能对应一个实体,就可以调用对应实体的DbSet的FormSqlInterPolated()方法来执行一个查询sql语句,同样使用字符串内插来传递参数

                SQL        select newid()        可用作随机排序

                like时需要参数传入"%中%",不能把%直接放入字符串中

                SQL        子查询中不能使用order By

        把只能用原生sql语句写的逻辑用FormSqlInterPolated()去执行,然后把分页,分组,二次过滤,排序,Include等其他逻辑尽可能仍然使用EFCore的标准操作去实现

        局限性

                1、sql查询必须返回实体类型对应数据库表的所有列;

                2、结果集中的列名必须与属性映射的列名称匹配;

                3、只能单表查询,不能使join语句进行关联查询,但是可以在查询后面使用Include()来进行关联数据的获取;

三、EFCore执行任意原生sql查询语句

        什么时候需要ADO.NET

                不推荐使用视图,存储过程

        执行任意sql

                ADO.NET 演示,操作太复杂不推荐

        Dapper框架

                演示,1、建对应DTO对象        2、Query方法

        总结

四、EFCore如何知道实体数据变了

        演示,SaveChanges时奇怪的地方,与数据库不一致的才会执行修改

        快照更改跟踪,概念

        实体的状态:已添加(Added),未改变(Unchanged),

                             已修改(Modified),已删除(Deleted),已分离/未跟踪(Datached)

                Savechanges的操作

        EntityEntry

                1、使用DbContext的Entry()方法来获得实体在EFCore中的跟踪信息对象EntityEntry,EntityEntry类的State属性代表实体的状态,通过DebugView.LongView属性可以看到实体的变化信息

                2、代码演示

        总结:DbContext会根据跟踪的实体的状态,在SaveChanges()的时候根据实体状态的不同,生成update,delete,inster等sql语句,来把内存中实体的变化更新到数据库中。这就是SaveChanges的原理

五、EFCore优化之AsNoTracking

        如果查询出来的对象不会被修改,删除等吗,那么查询时可以用AsNoTracking(),就能降低内存占用;不需要跟踪状态,不需要快照

        代码演示

六、EFCore实体状态跟踪的妙用(不推荐使用)

        修改和删除只执行一句sql语句,不用执行查询sql,可以性能优化,但代码可读性不强,难维护,提升微乎其微,弊大于利,不推荐使用;

七、EFCor数据的批量删除、更新、插入

        SQLBulkCopy        可以一次性把很多数据插入到数据库中

        演示,EFCore批量修改、删除、插如实体n条sql会执行

        为什么不用sql实现

                a、原生sql语句需要把表名、列名等硬编码到sql语句中,不符合模型驱动,分层隔离等思想,程序员直接面对数据库表,无法利用EFCore强类型的特性,如果模型发生改变,必须手动变更sql语句;

                b、无法利用EFCore强大的sql翻译机制来屏蔽不同底层数据库的差异

                c、EFCore官方迟迟未支持的原因

                        与EFCore实体状态跟踪冲突,会导致状态混乱

        我的开源实现        Zack.EFCore.Batch 包

                批量删除、更新、插入        使用方法,官方文档

                演示

八、全局查询筛选器

        EFCore会自动将这个查询筛选器应用于涉及这个实体类型的所有Linq查询

        场景:软删除,多租户(eg:商城系统商家入驻,每条记录都带有商户ID)

                软删除概念,代码演示

                builder.HasQueryFilter(a=>a.IsDeleted == false);

        忽略:ctx.Books.IgnoreQueryFilters().Where(b=>b.Age>10).ToArray();

        全局筛选器的性能陷阱:数据量大时,可能会造成全表扫描,根据情况优化系统,如:聚集索引

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值