ASP.NET Core 中使用 Dapper 的 Oracle 存储过程输出参数

介绍

Oracle 数据库功能强大,在企业环境中使用广泛。在 ASP.NET Core 应用程序中使用 Oracle 存储过程时,处理输出参数可能具有挑战性。本教程将指导您完成使用 Dapper(适用于 . NET 的轻量级 ORM(对象关系映射器))解锁 Oracle 存储过程输出参数的过程。

先决条件

在开始之前,请确保您已准备好以下内容。

  • Visual Studio 2019 或更高版本
  • .NET Core SDK 3.1 或更高版本
  • Oracle 数据库(您可以使用 Oracle 数据库 XE 进行开发)
  • 具有 C#、ASP.NET Core 和 SQL 的基础知识

设置项目

创建 ASP.NET 核心项目

打开 Visual Studio 并创建一个新的 ASP.NET Core 控制台应用程序项目。

安装 NuGet 包

您需要安装 Dapper 和 Oracle.ManagedDataAccess.Core 包。

创建 Oracle 存储过程

让我们在 Oracle 中创建一个简单的存储过程,它接受一个输入参数并返回一个输出参数。

CREATE OR REPLACE PROCEDURE DEMO.SAVE_EMPLOYEE_DETAILS (
   V_NAME        IN     VARCHAR2,
   V_ADDRESS     IN     VARCHAR2,
   V_DEPARTMENT  IN     VARCHAR2,
   V_POSITION    IN     VARCHAR2,
   O_EMP_ID      OUT    VARCHAR2,
   O_ERROR       OUT    VARCHAR2
)
AS
   V_EMP_ID VARCHAR2 (10);
BEGIN
   -- GENERATE EMPLOYEE ID
   SELECT DEMO.EMP_SEQ.NEXTVAL INTO V_EMP_ID FROM DUAL;

   -- INSERT EMPLOYEE DETAILS
   INSERT INTO DEMO.EMPLOYEE_DETAILS (
      EMP_ID,
      NAME,
      ADDRESS,
      DEPARTMENT,
      POSITION
   ) VALUES (
      V_EMP_ID,
      V_NAME,
      V_ADDRESS,
      V_DEPARTMENT,
      V_POSITION
   );
   -- SET OUTPUT EMPLOYEE ID
   O_EMP_ID := V_EMP_ID;

   -- RESET ERROR OUTPUT
   O_ERROR := NULL;
EXCEPTION
   WHEN OTHERS THEN
      O_ERROR := 'FAILED TO SAVE EMPLOYEE DETAILS. ' || SQLERRM;
      ROLLBACK;
      RETURN;
END SAVE_EMPLOYEE_DETAILS;
/

连接到 Oracle 数据库

使用 SQL*Plus、SQL Developer、Toad 或任何其他 Oracle 客户端工具连接到您的 Oracle 数据库。

实现 ASP.NET 核心应用程序

添加 OracleDynamicParameters 类

using Dapper;
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace DapperOracleDemo
{
    public class OracleDynamicParameters : SqlMapper.IDynamicParameters
    {
        private readonly DynamicParameters dynamicParameters = new DynamicParameters();
        // 使用DynamicParameters存储一般参数
        private readonly List<OracleParameter> oracleParameters = new List<OracleParameter>();
        // 使用List<OracleParameter>存储Oracle特定的参数

        public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction, object value = null, int? size = null)
        {
            // 创建并添加一个OracleParameter对象到参数列表中
            OracleParameter item = ((!size.HasValue) ? 
                new OracleParameter(name, oracleDbType, value, direction) : 
                new OracleParameter(name, oracleDbType, size.Value, value, direction));
            oracleParameters.Add(item);
        }

        public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction)
        {
            // 创建并添加一个没有默认值的OracleParameter对象到参数列表中
            OracleParameter item = new OracleParameter(name, oracleDbType, direction);
            oracleParameters.Add(item);
        }

        public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
        {
            // 将一般参数添加到命令对象中
            ((SqlMapper.IDynamicParameters)dynamicParameters).AddParameters(command, identity);
            // 将Oracle特定的参数添加到命令对象中
            (command as OracleCommand)?.Parameters.AddRange(oracleParameters.ToArray());
        }

        public T Get<T>(string name)
        {
            // 获取指定名称的参数值
            var parameter = oracleParameters.SingleOrDefault(t => t.ParameterName == name);
            object val = parameter?.Value;
            if (val == DBNull.Value)
            {
                if (default(T) != null)
                {
                    // 如果尝试将DBNull值转换为非可空类型,抛出异常
                    throw new ApplicationException("Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)");
                }
                return default;
            }
            return (T)val;
        }

        public T Get<T>(int index)
        {
            // 获取指定索引的参数值
            var parameter = oracleParameters[index];
            object val = parameter?.Value;
            if (val == DBNull.Value)
            {
                if (default(T) != null)
                {
                    // 如果尝试将DBNull值转换为非可空类型,抛出异常
                    throw new ApplicationException("Attempting to cast a DBNull to a non nullable type! Note that out/return parameters will not have updated values until the data stream completes (after the 'foreach' for Query(..., buffered: false), or after the GridReader has been disposed for QueryMultiple)");
                }
                return default;
            }
            return (T)val;
        }
    }
}

添加 OracleDataAccessObject 类

using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Data;

namespace DapperOracleDemo
{
    public class OracleDataAccessObject
    {
        private readonly string _ConnectionString;

        // 构造函数,初始化连接字符串
        public OracleDataAccessObject(string ConnectionString)
        {
            _ConnectionString = ConnectionString;
        }

        // 获取Oracle数据库连接
        private IDbConnection GetOracleConnection()
        {
            return new OracleConnection(_ConnectionString);
        }

        // 执行带参数的存储过程
        public dynamic OracleSProcWithParam(string sql, OracleDynamicParameters param)
        {
            // 使用using语句确保IDbConnection在使用后被正确关闭和释放
            using IDbConnection cnn = GetOracleConnection();
            CommandType? commandType = CommandType.StoredProcedure;
            // 执行存储过程
            return cnn.Execute(sql, param, null, null, commandType);
        }
    }
}

添加员工输入和输出 Dto

namespace DapperOracleDemo
{
    public class EmployeeInputDto
    {
        public string NAME { get; set; }
        public string ADDRESS { get; set; }
        public string DEPARTMENT { get; set; }
        public string POSITION { get; set; }
    }
}
namespace DapperOracleDemo
{
    public class EmployeeOutputDto
    {
        public string EMP_ID { get; set; }
        public string ERROR { get; set; }
    }
}
using Oracle.ManagedDataAccess.Types;
namespace DapperOracleDemo
{
    public class SpReturnModel
    {
        public dynamic ID { get; set; }
        public OracleString ErrorMsg { get; set; }
    }
}

配置连接字符串

static class Config
{
    public static string OracleDBConnectionString => "Data Source=192.168.29.1:1521/DEMODB;User Id=DEMO;Password=demo@123;";
    public static string SP_SAVE_EMPLOYEE_DETAILS = "DEMO.SAVE_EMPLOYEE_DETAILS";
}

添加 SaveEmployeeDetails() 方法

static SpReturnModel SaveEmployeeDetails(EmployeeInputDto dto)
{
    var oraDao = new OracleDataAccessObject(Config.OracleDBConnectionString);
    var oracleParam = new OracleDynamicParameters();
    oracleParam.Add("V_NAME", OracleDbType.Varchar2, ParameterDirection.Input, dto.NAME);
    oracleParam.Add("V_ADDRESS", OracleDbType.Varchar2, ParameterDirection.Input, dto.ADDRESS);
    oracleParam.Add("V_DEPARTMENT", OracleDbType.Varchar2, ParameterDirection.Input, dto.DEPARTMENT);
    oracleParam.Add("V_POSITION", OracleDbType.Varchar2, ParameterDirection.Input, dto.POSITION);
    oracleParam.Add("O_EMP_ID", OracleDbType.Varchar2, ParameterDirection.Output, size: 20);
    oracleParam.Add("O_ERROR", OracleDbType.Varchar2, ParameterDirection.Output, size: 2000);
    var oracleQuery = Config.SP_SAVE_EMPLOYEE_DETAILS;
    oraDao.OracleSProcWithParam(oracleQuery, oracleParam);
    return GetSpOutParamResult(oracleParam, "O_EMP_ID");
}
static SpReturnModel GetSpOutParamResult(OracleDynamicParameters param, string idParam = "")
{
    SpReturnModel retMdl = new SpReturnModel()
    {
        ID = !string.IsNullOrEmpty(idParam) ? param.Get<dynamic>(idParam) : 0,
        ErrorMsg = param.Get<OracleString>("O_ERROR")
    };

    return retMdl;
}

测试应用程序

调用 SaveEmployeeDetails() 方法

static void Main(string[] args)
{
    var inDto = new EmployeeInputDto
    {
        NAME = "SURYA RAJ GHIMIRE",
        ADDRESS = "KATHMANDU, NEPAL",
        DEPARTMENT = "RESEARCH & DEVELOPMENT",
        POSITION = "SOFTWARE ENGINEER"
    };
    var resp = SaveEmployeeDetails(inDto);
    var outDto = new EmployeeOutputDto
    {
        EMP_ID = resp.ID is null ? null : (string)resp.ID,
        ERROR = resp.ErrorMsg.ToString()
    };
    Console.WriteLine("Employee id: " + outDto.EMP_ID);
    Console.WriteLine("Error: " + outDto.ERROR);
    Console.ReadLine();
}

运行应用程序

运行您的 ASP.NET Core 应用程序并查看控制台上的输出。

结论

在本教程中,我们介绍了如何使用 Dapper 处理 ASP.NET Core 应用程序中 Oracle 存储过程的输出参数。通过遵循这些步骤,您可以有效地将 Oracle 存储过程集成到 .NET 应用程序中,利用 Dapper 的强大功能和简单性进行数据库操作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python数据分析-对驾驶安全数据进行了预测

一、研究背景和意义 随着汽车保有量的不断增加&#xff0c;交通事故已成为全球范围内的重大公共安全问题。每年因交通事故造成的人员伤亡和财产损失给社会带来了巨大的负担。为了提高驾驶安全&#xff0c;减少交通事故的发生&#xff0c;许多研究致力于探索影响驾驶安全的因素…

模式分解的概念(上)-分解、无损连接性、保持函数依赖特性

一、分解的概念 1、分解的定义 2、判断一个关系模式的集合P是否为关系模式R的一个分解 只要满足以下三个条件&#xff0c;P就是R的一个分解 &#xff08;1&#xff09;P中所有关系模式属性集的并集是R的属性集 &#xff08;2&#xff09;P中所有不同的关系模式的属性集之间…

如何通过自定义模块DIY出专属个性化的CSDN主页?一招教你搞定!

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 &#x1f4af;如何通过HTMLCSS自定义模板diy出自己的个性化csdn主页&#x…

本地快速部署大语言模型开发平台Dify并实现远程访问保姆级教程

文章目录 前言1. Docker部署Dify2. 本地访问Dify3. Ubuntu安装Cpolar4. 配置公网地址5. 远程访问6. 固定Cpolar公网地址7. 固定地址访问 前言 本文主要介绍如何在Linux Ubuntu系统使用Docker快速部署大语言模型应用开发平台Dify,并结合cpolar内网穿透工具实现公网环境远程访问…

解决element-plus没有导出的成员FormInstance

使用element-plus的el-form时&#xff0c;报错“"element-plus"”没有导出的成员“FormInstance”。你是否指的是“FooterInstance”? 解决方法&#xff1a; 引入ElForm类型&#xff0c;在外重新定义FormInstance的类型为ElForm的实例类型 示例&#xff1a; import…

记录keras库中导入函数找不到的问题

1 . keras.preprocessing.text import Tokenizer 将最右边的点 " . " 修改成 " _ " : 2 . 相应函数/库找不到&#xff0c;在keras后面加一个api :

基于AT32_Work_Bench配置AT32工程

基于AT32_Work_Bench配置AT32工程 ✨AT32_Work_Bench工具是用来给AT32 MCU快速构建外设初始化工程软件&#xff0c;类似STM32的STM32CubeMX工具软件。 &#x1f4cd;AT32 TOOL系列工具下载地址&#xff1a;https://www.arterytek.com/cn/support/index.jsp?index4&#x1f3f7…

C# WPF入门学习主线篇(二十八)—— 使用集合(ObservableCollection)

C# WPF入门学习主线篇&#xff08;二十八&#xff09;—— 使用集合&#xff08;ObservableCollection&#xff09; 在WPF中&#xff0c;数据绑定是构建动态和响应式用户界面的关键。ObservableCollection是一个特别有用的集合类型&#xff0c;它不仅支持数据绑定&#xff0c;还…

基于Elementui组件,在vue中实现多种省市区前端静态JSON数据展示并支持与后端交互功能,提供后端名称label和id

基于Elementui组件&#xff0c;在vue中实现多种省市区前端静态数据&#xff08;本地JSON数据&#xff09;展示并支持与后端交互功能&#xff0c;提供后端名称label和id 话不多说&#xff0c;先上图 1.支持传递给后端选中省市区的id和名称&#xff0c;示例非常完整&#xff0c…

【Java】线程池技术(二)ThreadPoolExecutor的基本定义

线程池初始化与定义 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)线程池构造方法的入参含义分别如下&…

C++的动态内存分配

使用new/delete操作符在堆中分配/释放内存 //使用new操作符在堆中分配内存int* p1 new int;*p1 2234;qDebug() << "数字是&#xff1a;" << *p1;//使用delete操作符在堆中释放内存delete p1;在分配内存的同时初始化 //在分配内存的时初始化int* p2 n…

chatgpt: linux 下用纯c 编写一按钮,当按钮按下在一新窗口显示hello world

用这个程序模板&#xff0c;就可以告别只能在黑框框的终端中编程了。 在 Linux 环境下使用纯 C 语言编写一个按钮&#xff0c;当按钮按下时&#xff0c;在一个新窗口显示 "Hello World"。我们可以使用 GTK 库来实现这个功能。GTK 是一个用于创建图形用户界面的跨平台…

第三十三篇-Ollama+AnythingLLM基本集成

AnythingLLM AnythingLLM专属私有知识库,可以使用本地OllamaLLM模型&#xff0c;可以上传文件&#xff0c;基于文件回答问题 启动ollama 参考 第二十五篇-Ollama-离线安装 第二十四篇-Ollama-在线安装 下载安装AnythingLLM https://useanything.com/downloadAnythingLLMDe…

C#使用NPOI库实现Excel的导入导出操作——提升数据处理效率的利器

文章目录 一、NPOI库简介二、安装与引入三、Excel的导入操作1.CSV格式导入2.XLS格式导入3. XLSX格式导入 四、Excel的导出操作1. CSV格式导出2. XLS格式导出3. XLSX格式导出 五、NPOI库的应用优势与改进方向总结 在日常工作学习中&#xff0c;我们经常需要处理Excel文件&#x…

【吊打面试官系列-Mysql面试题】什么是锁?

大家好&#xff0c;我是锋哥。今天分享关于 【什么是锁&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 什么是锁&#xff1f; 答&#xff1a;数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时&#xff0c;在数据库中就会产生多个事务同时存取同一…

RocketMQ快速入门:集成spring, springboot实现各类消息消费(七)附带源码

0. 引言 rocketmq支持两种消费模式&#xff1a;pull和push&#xff0c;在实际开发中这两种模式分别是如何实现的呢&#xff0c;在spring框架和springboot框架中集成有什么差异&#xff1f;今天我们一起来探究这两个问题。 1. java client实现消息消费 1、添加依赖 <depen…

运维 Tips | IT工程师常用的8个USB引导启动器工具

[ 知识是人生的灯塔&#xff0c;只有不断学习&#xff0c;才能照亮前行的道路 ] 【导语】本指南旨在深入探讨Linux上可用的前六个工具&#xff0c;以及Windows上使用两个U盘启动器生成及刻录工具&#xff0c;创建USB引导启动器用于引导系统ISO文件加载到计算机中&#xff0c;从…

LInux驱动开发笔记(十)SPI子系统及其驱动

文章目录 前言一、SPI驱动框架二、总线驱动2.1 SPI总线的运行机制2.2 重要数据结构2.2.1 spi_controller2.2.2 spi_driver2.2.3 spi_device2.2.4 spi_transfer2.2.5 spi_message 三、设备驱动的编写3.1 设备树的修改3.2 相关API函数3.2.1 spi_setup( )3.2.2 spi_message_init( …

在windows 台式机电脑部署GLM4大模型

参考这篇文章在windows笔记本电脑部署GLM4大模型_16g显卡本地部署glm4-CSDN博客 我的环境&#xff08;PC台式机电脑&#xff1a; 处理器 Intel(R) Core(TM) i9-14900K 3.20 GHz 机带 RAM 32.0 GB (31.8 GB 可用)、32G内存、NVIDIA RTX4080&#xff08;16G&#xff09;…

深入理解Open vSwitch(OVS):原理、架构与操作

一、引言 随着云计算和虚拟化技术的不断发展&#xff0c;网络虚拟化成为了构建灵活、可扩展网络架构的关键技术之一。Open vSwitch&#xff08;OVS&#xff09;作为一种功能强大的开源虚拟交换机&#xff0c;被广泛应用于云计算和虚拟化环境中&#xff0c;为虚拟机提供高效、灵…