SQLCLR으로 Webapi 핸들링
C#으로 Webapi 데이터를 연동하고 나니
MSSQL에 주기적으로 데이터를 넣어야한다고 한다.
프로그램에서 Timer로 돌리는 방법도 있겠지만 그냥 데이터베이스에서 처리할 수 없을까 찾아보았다
그 결과물
https://github.com/geral2/SQL-APIConsumer
geral2/SQL-APIConsumer
Database Project with generic procedures to consume API through GET/POST methods. - geral2/SQL-APIConsumer
github.com
SQLCLR 이라는 형식으로 프로젝트를 생성하고 해당 파일을 MSSQL에 어셈블리로 등록하면
C# 코드를 프로시저 형태로 사용할 수 있다.
해당 소스를 그대로 가져다쓰면 제대로 되지 않는 경우가 많으니
Webapi 호출 방식별로 프로그램에서 테스트 해본 후 데이터베이스에 적용시키는 편이 좋다.
나의 경우 Post 방식이었으며 다음과 같이 작성했다.
public static string POSTMethod_Header(string url, string Headers = "")
{
string ContentResult = string.Empty;
try
{
// 기본 API 링크 주소
string apiURL = url;
// 가져올 항목 STRING
string header = Headers;
byte[] contentBytes = Encoding.UTF8.GetBytes(header);
// 가져오는 방식 정의
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiURL);
request.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
request.Method = "POST";
request.KeepAlive = true;
request.ContentLength = contentBytes.Length;
// 인증서 오류 관련 처리 부분.
// 이 부분 없으면 진행되지 않음
ServicePointManager.ServerCertificateValidationCallback = delegate (
Object obj, X509Certificate certificate, X509Chain chain,
SslPolicyErrors errors)
{
return (true);
};
// 데이터 요청 구문
Stream st = request.GetRequestStream();
st.Write(contentBytes, 0, contentBytes.Length);
st.Close();
try
{
// 요청에 대한 데이터를 받는 구문
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string status = response.StatusCode.ToString();
if (status == "OK")
{
Stream stream = response.GetResponseStream();
string sResultJson = new StreamReader(stream).ReadToEnd();
ContentResult = sResultJson;
}
else
{
ContentResult = "Error :" + status;
}
st.Close();
response.Close();
}
catch (WebException ex)
{
ContentResult = ex.Message.ToString();
}
}
catch (Exception ex)
{
ContentResult = ex.Message.ToString();
throw ex;
}
return ContentResult;
}
이걸 어셈블리로 등록하는 과정 또한 험난한데
여기서 P1910은 데이터베이스 명이다.
use P1910
ALTER DATABASE P1910 SET COMPATIBILITY_LEVEL = 130
go
sp_configure 'clr enabled',1
RECONFIGURE
EXEC dbo.sp_changedbowner @loginame = N'sa', @map = false
ALTER DATABASE P1910 SET TRUSTWORTHY on
GO
CREATE ASSEMBLY [System.Runtime.Serialization]
AUTHORIZATION dbo
FROM N'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Runtime.Serialization.dll'
WITH PERMISSION_SET = UNSAFE--external_access
CREATE ASSEMBLY [System.Net.Http]
AUTHORIZATION dbo
FROM N'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Net.Http.dll'
WITH PERMISSION_SET = UNSAFE--external_access
CREATE ASSEMBLY [Newtonsoft.Json]
AUTHORIZATION dbo
FROM N'C:\CLR\Newtonsoft.Json.dll'
WITH PERMISSION_SET = UNSAFE
CREATE ASSEMBLY [APIConsumer]
AUTHORIZATION dbo
FROM N'C:\CLR\APIConsumer.dll'
WITH PERMISSION_SET = UNSAFE
go
CREATE PROCEDURE [dbo].[APICaller_POST_Headers]
@URL NVARCHAR (MAX) NULL, @Headers NVARCHAR (MAX) NULL
AS EXTERNAL NAME [APIConsumer].[StoredProcedures].APICaller_POST_Headers
GO
사용은 다음과 같이 하면 된다. 당연히 URL과 HEADER의 내용은 채워야겠죠
EXEC [dbo].[APICaller_POST_Headers]
@URL = URL
, @Headers = HEADER
등록한 후의 어셈블리 내역
프로젝트 참조 말고 DLL 참조로 디버깅 하세요.