实现SQLSERVER 调用 C# 代码

news2024/12/25 9:45:35

简单例子

首先写一段简单的 C# 代码,然后把它编译成 dll。

namespace Bussiness
{
    public class UserFunctions
    {
        public static string UserLogin(string username, string password)
        {
            var random = new Random();

            var isSuccess = random.Next() % 2 == 0;

            return isSuccess ? "登录成功" : "登录失败";
        }
    }
}

接下来需要做的就是数据库参数配置,开启 CLR 支持,并且指定某个数据库支持 unsafe 模式。 

EXEC sp_configure 'clr enabled', 1;
RECONFIGURE;
GO

ALTER DATABASE MyTestDB SET TRUSTWORTHY ON;
GO

 为了能够调到 C# 的 UserLogin 方法,需要 SQLSERVER 先导入这个程序集,然后再以 Function 映射其中方法即可

CREATE ASSEMBLY clr_Bussiness
FROM 'D:\Bussiness.dll'
WITH PERMISSION_SET = UNSAFE;
GO

CREATE FUNCTION dbo.clr_UserLogin
(
    @username AS NVARCHAR(100),
	@password AS NVARCHAR(100)
)
RETURNS NVARCHAR(100)
AS
EXTERNAL NAME clr_Bussiness.[Bussiness.UserFunctions].UserLogin;
GO

 创建完了之后,可以观察 assembly 开头的几个系统视图。

SELECT * FROM sys.assemblies
SELECT * FROM sys.assembly_files;
SELECT * FROM sys.assembly_modules;

接下来调用一下刚才创建的 clr_UserLogin 函数。

SELECT dbo.clr_UserLogin(N'jack',N'123456') AS 'State'
GO 10

 

 从图中看登录结果是随机的,说明 C# 的 Random 函数起到了作用。

WinDbg 观察

从案例的运行结果看,推测在 SQLSERVER 中应该承载了一个 CLR 运行环境,那是不是这样呢?可以用 WinDbg 附加到 sqlservr.exe 进程,用 lm观察下模块加载情况。

0:092> lm
start             end                 module name

...
00007ff8`d3960000 00007ff8`d3aaf000   clrjit     (deferred)    
00007ff8`de040000 00007ff8`deb02000   clr        (deferred)     
...

0:092> !eeversion
4.8.4300.0 free
Server mode with 12 gc heaps
SOS Version: 4.8.4300.0 retail build

从输出看果然加载了 clrclrjit 动态链接库,当前还是 gc server 模式。

接下来再验证一个问题,既然 clr_UserLogin 函数会显示 登录成功/登录失败,那必然会调用 C# 的 UserLogin 方法,可以在 WinDbg 中对 UserLogin 方法下一个断点观察一下这个调用过程

0:090> !name2ee Bussiness!Bussiness.UserFunctions.UserLogin
Module:      00007ff87ee37988
Assembly:    Bussiness, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Token:       0000000006000001
MethodDesc:  00007ff87ee38020
Name:        Bussiness.UserFunctions.UserLogin(System.String, System.String)
JITTED Code Address: 00007ff87ec560d0

0:090> bp 00007ff87ec560d0
0:090> g

从输出信息看 UserLogin 方法已经被 JIT 过了,用 bp 下完断点之后,继续 g,然后在 SSMS 上再次执行查询就可以成功命中啦。

0:090> k
 # Child-SP          RetAddr               Call Site
00 000000df`1557ae48 00007ff8`7ee500b6     0x00007ff8`7ec560d0
01 000000df`1557ae50 00007ff8`7ec55ef1     0x00007ff8`7ee500b6
02 000000df`1557aeb0 00007ff8`de04222e     0x00007ff8`7ec55ef1
03 000000df`1557af00 00007ff8`a2b79ff3     clr!UMThunkStub+0x6e
04 000000df`1557af90 00007ff8`a2b741bd     sqllang!CallProtectorImpl::CallWithSEH<AppDomainCallTraits,void,FunctionCallBinder_3<void,void (__cdecl*)(void (__cdecl*)(void * __ptr64),void * __ptr64,enum ESqlReturnCode * __ptr64),void (__cdecl*)(void * __ptr64),void * __ptr64,enum ESqlReturnCode * __ptr64> const >+0x23
05 000000df`1557afc0 00007ff8`a2b6bfc4     sqllang!CallProtectorImpl::CallExternalFull<AppDomainUserCallTraits,void,FunctionCallBinder_3<void,void (__cdecl*)(CXVariant * __ptr64,CXVariant * __ptr64,CClrLobContext * __ptr64),CXVariant * __ptr64,CXVariant * __ptr64,CClrLobContext * __ptr64> const >+0x2dd
06 000000df`1557b130 00007ff8`a2bda602     sqllang!CAppDomain::InvokeClrFn+0xd4
07 000000df`1557b1d0 00007ff8`aef51ee7     sqllang!UDFInvokeExternalImpl+0xb72
08 000000df`1557b7e0 00007ff8`9de52e24     sqlTsEs!CEsExec::GeneralEval4+0xe7
09 000000df`1557b8b0 00007ff8`9de52d64     sqlmin!CQScanProjectNew::EvalExprs+0x18f
0a 000000df`1557b920 00007ff8`9ddd8759     sqlmin!CQScanProjectNew::GetRow+0x98
0b 000000df`1557b970 00007ff8`9ddc73de     sqlmin!CQScanLightProfileNew::GetRow+0x19
0c 000000df`1557b9a0 00007ff8`a25e51d7     sqlmin!CQueryScan::GetRow+0x80
0d 000000df`1557b9d0 00007ff8`a32a78b2     sqllang!CXStmtQuery::ErsqExecuteQuery+0x3d8
0e 000000df`1557bb40 00007ff8`a2bc2451     sqllang!CXStmtSelect::XretDoExecute+0x342
0f 000000df`1557bc10 00007ff8`a2b733d3     sqllang!UM_LoopbackForStatementExecution+0x191
10 000000df`1557bd00 00007ff8`de48e940     sqllang!AppDomainCallback<FunctionCallBinder_5<void,void (__cdecl*)(CXStmtQuery * __ptr64,CCompExecCtxtStmt const * __ptr64,CMsqlExecContext * __ptr64,unsigned long * __ptr64,enum ESqlReturnCode * __ptr64),CXStmtQuery * __ptr64,CCompExecCtxtStmt const * __ptr64,CMsqlExecContext * __ptr64,unsigned long * __ptr64,enum ESqlReturnCode * __ptr64> >+0x23
11 000000df`1557bd40 00007ff8`de48e193     clr!ExecuteInAppDomainHelper+0x40
12 000000df`1557bd80 00007ff8`a2b79f39     clr!CorHost2::ExecuteInAppDomain+0x3a0
13 000000df`1557c0a0 00007ff8`a2b73a86     sqllang!CallProtectorImpl::CallWithSEH<AppDomainCallTraits,long,MethodCallBinder_3<long,ICLRRuntimeHost,long (__cdecl ICLRRuntimeHost::*)(unsigned long,long (__cdecl*)(void * __ptr64),void * __ptr64) __ptr64,unsigned long,long (__cdecl*)(void * __ptr64),void * __ptr64> >+0x29
14 000000df`1557c0d0 00007ff8`a2b6c2d0     sqllang!CallProtectorImpl::CallExternalFull<AppDomainCallTraits,long,MethodCallBinder_3<long,ICLRRuntimeHost,long (__cdecl ICLRRuntimeHost::*)(unsigned long,long (__cdecl*)(void * __ptr64),void * __ptr64) __ptr64,unsigned long,long (__cdecl*)(void * __ptr64),void * __ptr64> >+0x186
15 000000df`1557c170 00007ff8`a32a72f4     sqllang!CAppDomain::LoopbackForStatementExecution+0x180
16 000000df`1557c230 00007ff8`a32a79ad     sqllang!CXStmtQuery::XretCLRExecute+0x104
17 000000df`1557c2a0 00007ff8`a25e4a65     sqllang!CXStmtSelect::XretExecute+0x4a
18 000000df`1557c370 00007ff8`a25e44a8     sqllang!CMsqlExecContext::ExecuteStmts<1,1>+0x8f2
19 000000df`1557cf10 00007ff8`a25e3a2c     sqllang!CMsqlExecContext::FExecute+0x936
1a 000000df`1557def0 00007ff8`a25ee67b     sqllang!CSQLSource::Execute+0xc5c
1b 000000df`1557e3d0 00007ff8`a25ed815     sqllang!process_request+0xca6
1c 000000df`1557ead0 00007ff8`a25ed5ef     sqllang!process_commands_internal+0x4b7
1d 000000df`1557ec00 00007ff8`b1e46523     sqllang!process_messages+0x1d6
1e 000000df`1557ede0 00007ff8`b1e46e6d     sqldk!SOS_Task::Param::Execute+0x232
1f 000000df`1557f3e0 00007ff8`b1e46c75     sqldk!SOS_Scheduler::RunTask+0xa5
20 000000df`1557f450 00007ff8`b1e6b160     sqldk!SOS_Scheduler::ProcessTasks+0x39d
21 000000df`1557f570 00007ff8`b1e6aa5b     sqldk!SchedulerManager::WorkerEntryPoint+0x2a1
22 000000df`1557f640 00007ff8`b1e6afa4     sqldk!SystemThreadDispatcher::ProcessWorker+0x3ed
23 000000df`1557f940 00007ff8`f6d86fd4     sqldk!SchedulerManager::ThreadEntryPoint+0x3b5
24 000000df`1557fa30 00007ff8`f865cec1     KERNEL32!BaseThreadInitThunk+0x14
25 000000df`1557fa60 00000000`00000000     ntdll!RtlUserThreadStart+0x21

request 请求,然后达到了托管方法 UserLogin,顶部的三行线程栈可以用 !clrstack 

0:090> !clrstack
OS Thread Id: 0x6df4 (90)
        Child SP               IP Call Site
000000df1557ae48 00007ff87ec560d0 AQMN.Bussiness.UserFunctions.UserLogin(System.String, System.String)
000000df1557ae50 00007ff87ee500b6 DynamicClass.SQLCLR_Eval(IntPtr, IntPtr, IntPtr)
000000df1557aeb0 00007ff87ec55ef1 DomainBoundILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64)
000000df1557bf18 00007ff8de04222e [ContextTransitionFrame: 000000df1557bf18] 

看来SQLSERVER 内嵌了 CLR,让 sqlservr 进程成了一种托管和非托管的混合环境,托管的 C#,VB,F# 可以助 SQLSERVER 更加强大。 

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

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

相关文章

【漏洞复现】钉钉rce反弹shell

文章目录 一、漏洞描述二、漏洞原理三、影响版本四、复现过程0.环境说明1.msf 生成shellcode2.msf开启监听3.将生成的shellcode替换原shellcode4.开启web服务&#xff0c;并上传poc文件&#xff0c;构造poc5.从钉钉发送poc给受害者6.受害者点击即会触发漏洞&#xff0c;在msf监…

前端菜鸟如何快速开发个人产品

我是车辙&#xff0c;我的掘金小册《SkyWalking&#xff1a;应用监控和链路跟踪》已经上线啦&#xff0c;这是我的第一本电子书&#xff0c;欢迎大家订阅。 大家好&#xff0c;我是车辙。在完成小册后的一段时间&#xff0c;我突然想开发一款个人H5产品。在起初有这样想法的时候…

长、中、短视频“再战”微短剧

配图来自Canva可画 近年来&#xff0c;流量焦虑一直伴随着国内的视频平台&#xff0c;比如&#xff0c;制作精良的长视频由于剧集冗长正在被“追求效率”的年轻人抛弃&#xff1b;高歌猛进的短视频也因为无法承受太多有价值的内容而面临增长瓶颈。在此背景下&#xff0c;制作门…

中国工业以太网交换机市场分析

一、我国以太网交换机市场&#xff1a; 工业以太网交换机&#xff08;IndustrialEthernetSwitches&#xff09;是能够满足工业现场需要&#xff0c;技术层面与商业以太网交换机适配&#xff0c;而实时通信、可靠性、稳定性、安全性、环境适应性等各个方面规定高于商业以太网交…

玩转X3派,健身游戏两不误

一、准备工作 Windows电脑端安装拳皇游戏 &#xff08;因为是按键模拟&#xff0c;理论上只要是按键控制的游戏都可以玩&#xff0c;本文用MAME模拟器作例子&#xff0c;下载MAME&#xff1a;MAMEdev.org | Home of The MAME Project&#xff09; Windows可直接从该目录下载&…

常用的PHP伪协议大全

目录 常见文件包含函数 常见协议 php:// php://filter&#xff08;本地磁盘文件进行读取&#xff09; php://input &#xff08;读取POST数据&#xff09; file:// data:// 常见文件包含函数 函数功能include()代码执行到 include() 函数时将文件包含include_once()当…

如何操作工单系统

如何自定义工单字段 点击【工单管理】 > 点击【工单自定义字段】。选择【添加新的自定义字段】&#xff0c;即可进行字段编辑。管理人员可以在此页面自行添加要在工单上显示的内容&#xff0c;更改工单的格式&#xff0c;使其更满足于自身实际操作需要。管理员可选择添加单…

从“少林寺”毕业后,我当上了开源社区“区长”

本期名人堂我们有幸邀请到了Alluxio创始成员兼开源社区副总裁范斌先生。范斌先生讲述了自己的求学、工作、加入开源社区的经历&#xff0c;以及对未来十年数据编排发展的展望&#xff0c;和对开发贡献者的一些建议。 问题 1&#xff1a;范斌老师您好&#xff0c;很荣幸有机会采…

归并排序与逆序对数量模板题

归并排序 归并排序模板题 给定你一个长度为 n 的整数数列。 请你使用归并排序对这个数列按照从小到大进行排序。 并将排好序的数列按顺序输出。 输入格式 输入共两行&#xff0c;第一行包含整数 n。 第二行包含 n 个整数&#xff08;所有整数均在 1∼109 范围内&#xff…

DCG开年大戏上演“拖字诀”,爆雷恐迎加密至暗时刻

文/章鱼哥出品/陀螺财经币圈无新事&#xff0c;新年伊始&#xff0c;DCG被Gemini催债引发爆雷传言的事情一如FTX、SBF爆雷当初 &#xff0c;DCG是否会步他们的后尘&#xff0c;目前还不得而知&#xff0c;但这开年一记重锤&#xff0c;给2023的加密领域开了个坏头。祸起Gemini …

【王道·计算机网络】第一章 计算机网络基本体系【未完】

1. 计算机网络概述 1. 概念 计算机网络是一个将分散的、具有独立功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。简而言之&#xff0c;计算机网络就是一些互联的(通过通信链路互联互通)、自治的计算机系…

【4.1】Ribbon负载均衡原理

【4.1】Ribbon负载均衡1 Ribbon--负载均衡原理1.1 负载均衡流程1.2 源码分析&#xff08;debug&#xff09;2 总结1 Ribbon–负载均衡原理 1.1 负载均衡流程 图中的地址是真实可用的地址吗&#xff1f; 显然不是。 这样一个请求实际上是无法直接到达user-service的。 因此中间…

求一款免费好用的进销存管理软件?

求一款免费好用的进销存管理软件&#xff1f; 免费好用的进销存管理软件&#xff0c;“免费”一词对用户最具吸引力。 很多的小微企业在企业发展的过程都会选择免费的进销存管理软件来协助自己运营。都会希望&#xff0c;花最低的成本&#xff0c;实现最大的利益。 进销存管…

牛客网数据库sql实战剖析(一)

牛客网SQL实战 1.查找最晚入职员工的所有信息 思路&#xff1a;找出入职时间最大的时间&#xff0c;作为子查询条件进一步查找到该员工的其它信息。 SELECT * FROM employees WHERE hire_date (SELECT MAX(hire_date)FROM employees );这里不能用order by的方式&#xff0c…

私募证券基金动态-12月报

成交量&#xff1a;2022全年日均9,277.25亿元12月A股两市日均成交7,875.28亿元&#xff0c;环比下降15.15%、同比下降26.83%&#xff0c;是2022年继9月以后成交量次低的月份。2022年全年&#xff0c;日均成交量9,277.25亿元。管理人&#xff1a;新提交备案29家&#xff0c;备案…

【北京理工大学-Python 数据分析-1.2-NumPy数据存储与函数】

一、数据CSV文件的存取 CSV文件&#xff08;Comma-Separated Value,逗号分隔值&#xff09;是一种常见的文件格式&#xff0c;用来存储批量数据。 如常见的数据存储为CSV后 NumPy中有两个函数可以写入CSV格式&#xff0c;并从CSV文件中读取数据。 CSV文件的存储 np.savetxt…

mysql中的rand()函数简介以及和其他函数组合使用实践

一、本文结构简介 本文首先介绍rand()的基本使用 其次分别介绍round与rand的合用、ceiling与rand的合用、floor与rand的合用、md5与rand的合用 二、rand()的基本使用 rand()是系统自带的获取随机数的函数 (1)无参数&#xff1a;产生获取[0,1)之间的float型的数字 (2)有参数&a…

【jQuery】写一个电梯导航

今天大概是跟着pink老师学习JS的第八天&#xff0c;看了有410章了。 视频教程&#xff1a;pink JS 今天早上跟着老师做了一个电梯导航&#xff1a; 还是那个熟悉的品优购项目。。。 之后我打算自己练习一下&#xff0c;然后就出现bug了。 <div class"tuijian"&…

CO13 订单取消确认报错:“在为订单XXXX 确定实际成本中出错”处理分析

用户再操作CO13时报了一个错误&#xff1a;在为订单XXXX 确定实际成本中出错。 看到这个错误以为是财务同时没有发布成本导致的。然后我也操作了一下发现了一些过账中的错误。 原来是冲销这个工单的账期是在前几个月&#xff0c;而那个月已经关账期了&#xff0c;所以报错。 …

ORB-SLAM3代码和算法学习—浅谈代码中的纯定位模式

0总述 在Tracking线程中&#xff0c;当系统初始化完成后就会正式进入跟踪环节。在ORB-SLAM3算法代码中提供了两种模式&#xff0c;一种是纯定位模式&#xff0c;一种是定位建图的SLAM模式。 对于纯定位模式&#xff0c;在源码中由成员变量mbOnlyTracking控制&#xff0c;这个…