1:背景1.讲故事前几天看到一个奇怪的Function函数,调用了C#链接库中的一个UserLogin方法。参考代码如下:CREATEFUNCTIONdbo.clr_UserLogin(@nameASNVARCHAR(100),@passwordASNVARCHAR(100))返回INTASEXTERNALNAMEasmXXX.[xxx.CLRFunctions].UserLogin;GO这让我很感兴趣,众所周知SQLSERVER是用C++写的,那么这里的C++是怎么和C#打通的呢?此外,C#是一种托管语言,需要JIT才能使其成为原生语言。这个JIT在哪里?让我们带着这些问题一起来研究。二:互操作性原理研究1.一个简单的例子先写一段简单的C#代码,然后编译成dll。namespaceAQMN.Bussiness{publicclassUserFunctions{publicstaticstringUserLogin(stringusername,stringpassword){varrandom=newRandom();varisSuccess=random.Next()%2==0;返回成功?"登录成功":"登录失败";}}}接下来要做的是配置数据库参数,开启CLR支持,指定一个数据库支持不安全模式。EXECsp_configure'clrenabled',1;RECONFIGURE;GOALTERDATABASEMyTestDBSETTRUSTWORTHYON;GO为了能够调用到C#的UserLogin方法,SQLSERVER需要先导入这个程序集,然后使用Function映射方法。参考代码如下:CREATEASSEMBLYclr_AQMN_BussinessFROM'D:\net6\SQLCrawl\AQMN.Bussiness\bin\Debug\AQMN.Bussiness.dll'WITHPERMISSION_SET=UNSAFE;GOCREATEFUNCTIONdbo.clr_UserLogin(@usernameASNVARCHAR(100),@password10ASNVARCHAR())返回NVARCHAR(100)ASEXTERNALNAMEclr_AQMN_Bussiness.[AQMN.Bussiness.UserFunctions].UserLogin;GO创建后,可以观察到组装开始时的几个系统视图。选择*来自sys.assembliesSELECT*来自sys.assembly_files;选择*来自sys.assembly_modules;好像没什么问题,那就调用刚刚创建的clr_UserLogin函数。SELECTdbo.clr_UserLogin(N'jack',N'123456')AS'State'GO10从图中可以看出登录结果是随机的,说明C#的Random函数发挥了作用,很有意思。2.WinDbg观察从案例的运行结果来看,推测应该是在SQLSERVER中承载了一个CLR运行环境,是这样吗?您可以使用WinDbg附加到sqlservr.exe进程并使用lm观察模块加载。0:092>lmstart结束模块名称...00007ff8`d396000000007ff8`d3aaf000clrjit(延迟)00007ff8`de04000000007ff8`deb02000clr(延迟)...0:092>!eeversion4.8.4300.0withOSfreeSerapVersion:4.8.4300.0retailbuild从输出来看,加载了clr和clrjit动态链接库,还是gcserver模式。