20230223-EF6用原生的命令执行SQL命令

news2024/11/24 12:34:48

目录:

一、环境说明

二、背景

三、示例代码

四、思考总结

一、环境说明

本机环境:windows10 操作系统
使用工具:Visual Studio 2022
Net版本:Net6.0

二、背景

在使用winform EF 开发过程中,需要用到类似 QueryList QueryScalar 等功能的时候,发现EF6只提供标量的List列表,且在一个context中,QueryScalar(执行SQL命令的事务有问题,无法更新到数据),所以需要一个扩展来执行特定的命令(SQL语句),以及可以实现动态的(dynamic)类型来满足开发需要。

官网参考资料 :

https://learn.microsoft.com/zh-cn/ef/core/querying/sql-queries

查询标量(非实体)类型

备注

EF Core 7.0 中已引入此功能。

虽然可以使用 FromSql 来查询模型中定义的实体,但如果使用 SqlQuery,你就可以通过 SQL 轻松查询非实体标量类型,无需下降到较低级别的数据访问 API。 例如,以下查询从 Blogs 表中提取所有 ID:C#复制

var ids = context.Database
    .SqlQuery<int>($"SELECT [BlogId] FROM [Blogs]")
    .ToList();

还可以在 SQL 查询的基础上组合使用 LINQ 运算符。 但是,由于 SQL 成为子查询,其输出列需要由 SQL EF 添加项来引用,因此必须为输出列 Value 命名。 例如,以下查询返回的 ID 高于 ID 平均值:C#复制

var overAverageIds = context.Database
    .SqlQuery<int>($"SELECT [BlogId] AS [Value] FROM [Blogs]")
    .Where(id => id > context.Blogs.Average(b => b.BlogId))
    .ToList();

FromSql 可与数据库提供程序支持的任何标量类型配合使用。 如果想要使用数据库提供程序不支持的类型,可以使用约定前配置为其定义值转换。

SqlQueryRaw 允许动态构造 SQL 查询,就像 FromSqlRaw 对实体类型所做的那样。

执行非查询 SQL

在某些情况下,可能需要执行不返回任何数据的 SQL,通常用于修改数据库中的数据或调用不返回任何结果集的存储过程。 可以通过 ExecuteSql 完成此操作:C#复制

using (var context = new BloggingContext())
{
    var rowsModified = context.Database.ExecuteSql($"UPDATE [Blogs] SET [Url] = NULL");
}

它会执行提供的 SQL 并返回修改的行的数目。 ExecuteSql 使用安全的参数化来防止 SQL 注入,就像 FromSql 一样,而 ExecuteSqlRaw 允许动态构造 SQL 查询,就像 FromSqlRaw 对查询所做的那样。

备注

在 EF Core 7.0 之前,有时必须使用 ExecuteSql API 对数据库执行“批量更新”,如上所示;这比在查询所有匹配行后使用 SaveChanges 来修改它们要高效得多。 EF Core 7.0 引入了 ExecuteUpdate 和 ExecuteDelete,因此可以通过 LINQ 表达高效的批量更新操作。 建议尽可能使用这些 API 而非 ExecuteSql。

限制

从 SQL 查询返回实体类型时,需注意以下几个限制:

  • SQL 查询必须返回实体类型的所有属性的数据。

  • 结果集中的列名必须与属性映射到的列名称匹配。 请注意,此行为与 EF6 不同;EF6 忽略了 SQL 查询的属性-列映射,只需结果集列名与这些属性名相匹配即可。

  • SQL 查询不能包含关联数据。 但是,在许多情况下你可以在查询后面紧跟着使用

Include 方法以返回关联数据(请参阅包含关联数据)。

三、示例代码

说明:编写扩展程序,用基本的SQL语句支持动态或者泛型支持执行数据库

程序代码:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace .......config
{
    /// <summary>
    /// DbContextExtension
    /// </summary>
    public static class DbContextExtension
    {
        /// <summary>
        /// QueryList
        /// </summary>
        /// <param name="context"></param>
        /// <param name="sql"></param>
        /// <param name="map"></param>
        /// <returns></returns>
        public static IEnumerable<dynamic> QueryList(this DbContext context, string sql, Dictionary<string, object>? map = null)
        {
            using (var cmd = context.Database.GetDbConnection().CreateCommand())
            {
                CmdExecute(cmd, sql, map);
                using (var dataReader = cmd.ExecuteReader())
                {
                    while (dataReader.Read())
                    {
                        var row = new ExpandoObject() as IDictionary<string, object>;
                        for (var fieldCount = 0; fieldCount < dataReader.FieldCount; fieldCount++)
                        {
                            row.Add(dataReader.GetName(fieldCount), dataReader[fieldCount]);
                        }
                        yield return row;
                    }
                }
            }
        }

        /// <summary>
        /// QueryList
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <param name="sql"></param>
        /// <param name="itemReader"></param>
        /// <param name="map"></param>
        /// <returns></returns>
        public static IEnumerable<T> QueryList<T>(this DbContext context, string sql, Func<IDataReader, T> itemReader, Dictionary<string, object>? map = null)
        {
            using (var cmd = context.Database.GetDbConnection().CreateCommand())
            {
                CmdExecute(cmd, sql, map);
                using (var dataReader = cmd.ExecuteReader())
                {
                    while (dataReader.Read())
                    {
                        yield return itemReader(dataReader);
                    }
                }
            }
        }

        /// <summary>
        /// QueryList
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <param name="sql"></param>
        /// <param name="itemReader"></param>
        /// <param name="map"></param>
        /// <returns></returns>
        public static T? QueryScalar<T>(this DbContext context, string sql, Dictionary<string, object>? map = null)
        {
            using (var cmd = context.Database.GetDbConnection().CreateCommand())
            {
                CmdExecute(cmd, sql, map);
                object? result = cmd.ExecuteScalar();
                return result is DBNull ? default(T) : (T)result!;
            }
        }

        /// <summary>
        /// CmdExecute
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="sql"></param>
        /// <param name="map"></param>
        private static void CmdExecute(DbCommand cmd, string sql, Dictionary<string, object>? map)
        {
            cmd.CommandText = sql;
            if (null != cmd.Connection && cmd.Connection.State != ConnectionState.Open) { cmd.Connection.Open(); }
            if (null != map)
            {
                foreach (KeyValuePair<string, object> p in map)
                {
                    DbParameter dbParameter = cmd.CreateParameter();
                    dbParameter.ParameterName = p.Key;
                    dbParameter.Value = p.Value;
                    cmd.Parameters.Add(dbParameter);
                }
            }
        }
    }
}

调用主要代码:

四、思考总结

///核心代码

        /// <summary>
        /// QueryList
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <param name="sql"></param>
        /// <param name="itemReader"></param>
        /// <param name="map"></param>
        /// <returns></returns>
        public static T? QueryScalar<T>(this DbContext context, string sql, Dictionary<string, object>? map = null)
        {
            using (var cmd = context.Database.GetDbConnection().CreateCommand())
            {
                CmdExecute(cmd, sql, map);
                object? result = cmd.ExecuteScalar();
                return result is DBNull ? default(T) : (T)result!;
            }
        }

        /// <summary>
        /// CmdExecute
        /// </summary>
        /// <param name="cmd"></param>
        /// <param name="sql"></param>
        /// <param name="map"></param>
        private static void CmdExecute(DbCommand cmd, string sql, Dictionary<string, object>? map)
        {
            cmd.CommandText = sql;
            if (null != cmd.Connection && cmd.Connection.State != ConnectionState.Open) { cmd.Connection.Open(); }
            if (null != map)
            {
                foreach (KeyValuePair<string, object> p in map)
                {
                    DbParameter dbParameter = cmd.CreateParameter();
                    dbParameter.ParameterName = p.Key;
                    dbParameter.Value = p.Value;
                    cmd.Parameters.Add(dbParameter);
                }
            }
        }
    }

上述代码通过 context.Database.GetDbConnection().CreateCommand() 得到Command , 然后根据底层的SQL命令进行执行原来的逻辑。根据需要的场景满足业务需求,后续代码可以进一步封装进行泛型变换,支持VO BO 等面向领域对象的获取,欢迎大家沟通。

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

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

相关文章

MySQL中MVCC如何解决不可重复读以及幻读?

了解MVCC之前&#xff0c;我们首先需要了解以下两个概念&#xff1a;一致性非锁定读和锁定读&#xff0c;了解这两个概念之后我们在逐步分析MVCC。 一致性非锁定读和锁定读 一致性非锁定读(快照读) 对于 一致性非锁定读的实现&#xff0c;通常做法是加一个版本号或者时间戳字…

【12-JVM面试专题-垃圾回收器好坏评价的标准?吞吐量和响应时间?生产环境中,如何选择合适的垃圾收集器?如何判断是否使用G1垃圾收集器?】

垃圾回收器好坏评价的标准&#xff1f;吞吐量和响应时间&#xff1f;生产环境中&#xff0c;如何选择合适的垃圾收集器&#xff1f;如何判断是否使用G1垃圾收集器&#xff1f; 垃圾回收器好坏评价的标准&#xff1f;吞吐量和响应时间&#xff1f;生产环境中&#xff0c;如何选择…

python基于vue戒烟网站

可定制框架:ssm/Springboot/vue/python/PHP/小程序/安卓均可开发目录 开发语言&#xff1a;Python python框架&#xff1a;django/flask 软件版本&#xff1a;python 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;PyCharmscode 项目介…

Java常用算法

关于时间复杂度&#xff1a; 平方阶 (O(n2)) 排序 各类简单排序&#xff1a;直接插入、直接选择和冒泡排序。线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序。O(n1)) 排序&#xff0c; 是介于 0 和 1 之间的常数。希尔排序。线性阶 (O(n)) 排序 基数排序&#xff0c…

技能提升:Python技术应用工程师职业技能提升

职业技术培训-Python技术应用工程师分为高级培训班、中级培训班及初级培训班。 Python是一种跨平台的计算机程序设计语言&#xff0c;是一个高层次的结合了解释性、编译性、互动性和面向对象的语言。最初被设计用于编写自动化脚本Shell&#xff08;适用于Linux操作系统&#xf…

2-并发篇

线程有哪些状态 java的线程状态有6种&#xff1a; 操作系统中有5状态的说明 注意java的runnable对应了就绪、运行、阻塞I/O 线程池的核心参数 主要是说线程池的一个实习类 threadPoolExecutor.class 1.corePoolSize 核心线程数据&#xff08;可以为0&#xff09; 最多保…

第一章:网络参考模型

一、专业术语 ISO---&#xff08;International Organization for Standardization&#xff09;国际标准化组织 OSI---&#xff08;Open System Interconnection Reference Model&#xff09;开放式系统互联通信参考模型 IEEE---(Institute of Electrical and Electronics Engi…

数字经济赋能乡村建设,助力乡村全面振兴

我国农村正朝着全面振兴的方向迈步发展&#xff0c;与此同时&#xff0c;我国高速发展的数字经济正在成为驱动经济社会全方位高质量发展的重要引擎&#xff0c;数字经济赋能乡村建设是乡村振兴的重要战略方向。数字经济通过将数据要素纳入农业生产、将数字产品和服务融入农民生…

3年经验,3轮技术面+1轮HR面,拿下字节30k*16薪offer,这些自动化测试面试题值得大家借鉴

面试一般分为技术面和hr面&#xff0c;形式的话很少有群面&#xff0c;少部分企业可能会有一个交叉面&#xff0c;不过总的来说&#xff0c;技术面基本就是考察你的专业技术水平的&#xff0c;hr面的话主要是看这个人的综合素质以及家庭情况符不符合公司要求&#xff0c;一般来…

K8s调度器Scheduler

当创建k8s pod的时候调度器会决定pod在哪个node上被创建且运行&#xff0c;调度器给apiserver发出了一个创建pod的api请求&#xff0c;apiserver首先将pod的基本信息保存在etcd&#xff0c;apiserver又会把这些信息给到每个node上的kubelet进程&#xff0c;kubelet一直在监听这…

Arduino UNO驱动土壤湿度传感器检测

Arduino UNO驱动土壤湿度传感器检测简介运行要求Arduino UNO与传感器接线程序展示实践效果总结简介 本次使用到是这个新款土壤湿度传感器&#xff01; 这款电容式土壤湿度传感器区别于市面上绝大部分的电阻式传感器&#xff0c;采用电容感应原理来检测土壤湿度。避免了电阻式传…

电子技术——系统性分析反馈电压放大器

电子技术——系统性分析反馈电压放大器 在本节我们提供一个系统性的分析反馈电压放大器的方法。首先我们考虑反馈网络没有负载效应理想情况&#xff0c;其次我们考虑反馈网络有限阻抗下的非理想情况。总之&#xff0c;这种方法的思路在于&#xff0c;将非理想情况转换为理想情况…

CVE-2022-22947 SpringCloud GateWay SPEL RCE 漏洞分析

漏洞概要 Spring Cloud Gateway 是Spring Cloud 生态中的API网关&#xff0c;包含限流、过滤等API治理功能。 Spring官方在2022年3月1日发布新版本修复了Spring Cloud Gateway中的一处代码注入漏洞。当actuator端点开启或暴露时&#xff0c;可以通过http请求修改路由&#xff…

Linux 平台 RTSP server项目开发总结

先看下效果 Demo版本限制了只支持两个通道 每个通道只能连接一个客户端 FULL版本 没有这个限制 需要全功能版本 请联系博主 so库和测试demo可以点击这里下载 功能说明如下&#xff1a; 视频支持H264/H265音频支持AAC只支持LIVE 不支持文件点播支持TCP/UDP不支持RTCP支持多用…

Unity之ASE实现“软溶解”

前言 软溶解是相对之前将的硬边溶解来说的&#xff0c;软溶解顾名思义&#xff0c;就是溶解的边缘会比较平滑柔和&#xff0c;不像硬边溶解那样溶解边缘是清晰的。所以在游戏中也常被人所使用。效果请看下图&#xff1a; 硬边溶解原理 我们还记得之前讲应变溶解时的节点吗&…

如何快速一次性通过pmp考试?

我们就从三个方向进行了解 1.PMP考试难不难&#xff1f; 2.PMP如何备考&#xff1f; 3.考试过程中需要注意什么&#xff1f; 一&#xff0c;PMP考试难不难&#xff1f; 首先关注的问题是&#xff0c;PMP考试难吗&#xff1f;我想全球55%的通过率和学会这边93.9%的通过率&a…

架构基本概念和架构本质

什么是架构和架构本质 在软件行业&#xff0c;对于什么是架构&#xff0c;都有很多的争论&#xff0c;每个人都有自己的理解。此君说的架构和彼君理解的架构未必是一回事。因此我们在讨论架构之前&#xff0c;我们先讨论架构的概念定义&#xff0c;概念是人认识这个世界的基础&…

宣布 Databricks 支持 Amazon Graviton2,性价比提高3倍

今天&#xff0c;我们很高兴地宣布 Databricks 对基于 Amazon Graviton2 的亚马逊弹性计算云&#xff08;Amazon EC2&#xff09;实例的支持的公开预览。Graviton 处理器由亚马逊云科技进行定制设计和优化&#xff0c;为运行在 Amazon EC2 上的云工作负载提供最佳性价比。当与高…

CSS字体样式(font)[详细]

CSS字体样式&#xff08;font&#xff09;1. font-family2. font-style3. font-weight4. font-size5. font-variant6. fontCSS 中提供了一系列用于设置文本字体样式的属性&#xff0c;比如更改字体&#xff0c;控制字体大小和粗细等等。font-family&#xff1a;设置字体&#x…

【LeetCode】剑指 Offer 12. 矩阵中的路径 p89 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/ju-zhen-zhong-de-lu-jing-lcof/ 1. 题目介绍&#xff08;12. 矩阵中的路径&#xff09; 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&…