Выполнение VB.NET DLL из SQL Server

Задача:

мы хотим написать DLL, используя VB.NET 2008, используя.Net 3.5, который выполняет HTTP-запрос

Затем мы хотим вызвать DLL из SQL Server 2005 (в триггере) и передать DLL некоторые переменные и получить возвращаемое значение.

Где я нахожусь в процессе.

Я создал DLL 'HTTPDLL.dll'

Источник:

Imports System
Imports System.Configuration
Imports System.Collections.Generic
Imports System.Text
Imports System.Net
Imports System.Security
Imports System.Security.Permissions
Imports System.IO
Imports Microsoft.SqlServer.Server



Public Class HTTPDLL

Public Function HTTPPost(ByVal URL As String, ByVal Content As String) As Boolean

    Dim myURL As String = Trim(URL)
    Dim mycontent As String = Trim(Content)
    Dim rawOutput As String = ""

    'Get Acces Right to web
    Dim p As New WebPermission(NetworkAccess.Connect, myURL)
    p.Assert()

    'Prepare the web Request
    Dim req As WebRequest = WebRequest.Create(myURL)
    req.Timeout = 60000
    req.Method = "POST"
    req.ContentLength = mycontent.Length
    req.ContentType = "application/x-www-form-urlencoded"

    Dim sw As New StreamWriter(req.GetRequestStream())
    sw.Write(mycontent)
    sw.Close()

    Dim resp As WebResponse = req.GetResponse()
    Dim sr As New StreamReader(resp.GetResponseStream)
    rawOutput = sr.ReadToEnd()
    sr.Close()
    Return True


End Function

Public Function Test() As Integer
    Return 1
End Function


Public Function DllMain(ByVal hInst As Long, ByVal fdwReason As Long, _
ByVal lpvReserved As Long) As Boolean

    Dim s As String =     "sdfghjkolihdgjkhgiueghkyhekygigdjhgfkhsgdkhfgksjdhgkjshdgfkjhsgdkjfhgkshdgfkjhgskjdhgfkjhsdgkfhgskjdhfgkjsdhgfkshdgfkhgsdkfhgksdhfgkshdgfkshdgfkjhsgdkfhgskdhfgksjdhgfkjshgdfkhsgdkfhgskdhfgkshgdfkjhgskdjg"
    s &= "kjhdgjkshkdjfhklsjdhfljhgkhvbfiuvbli klrfgliu ghliebliuhdflivbdkljhgljuhfvliuhdf"
    Return True

End Function

End Class

Я поместил DLL в папку SQL Server c:/Windows/System

Я загрузил эти сборки

HelloWorld System.Core System.XML.Linq

используя эти команды

EXEC sp_configure 'show advanced options' , '1';
go
reconfigure
go

EXEC sp_configure 'clr enabled' , '1'
go

sp_configure 'Ole Automation Procedures', '1'
GO 
RECONFIGURE

-- Turn advanced options back off
EXEC sp_configure 'show advanced options' , '0';
go
reconfigure
GO
-- assembly style
ALTER DATABASE master SET TRUSTWORTHY ON
GO

CREATE ASSEMBLY [System.Core]
AUTHORIZATION [dbo]
FROM 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll'
WITH PERMISSION_SET = UNSAFE
GO

CREATE ASSEMBLY [System.Xml.Linq]
AUTHORIZATION [dbo]
FROM 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll'
WITH PERMISSION_SET = UNSAFE
GO

create assembly HelloWorld from 'C:\WINDOWS\system\HTTPDLL.dll'
with permission_set = safe
GO

Затем я добавил расширенную процедуру

USE [master]
GO
/****** Object:  ExtendedStoredProcedure [dbo].[HTTPDLL]    Script Date: 02/03/2010 11:45:28 ******/
EXEC dbo.sp_addextendedproc N'HTTPDLL', 'C:\WINDOWS\system\HTTPDLL.dll'

(на данный момент я не уверен, почему или если мне нужно было добавить сборку, так как это напрямую ссылается на Dll.)

То, что мне нужно, решено. Теперь я хочу вызвать функцию HTTPPost (расширенную процедуру) DLL

Что я пробовал exec HTTPPost "Сообщение 17750, уровень 16, состояние 0, процедура HTTPPost, строка 1 Не удалось загрузить DLL HelloWorld или одну из библиотек DLL, на которые она ссылается. Причина: 126(Указанный модуль не найден.). "

exec HelloWorld.HTTPPost 'http://www.somewebsite.com',''

"Сообщение 2812, уровень 16, состояние 62, строка 1 Не удалось найти хранимую процедуру HelloWorld.HTTPPost".

Что мне нужно: если вы можете просмотреть мою имплиментацию и посмотреть, правильно ли я все настраиваю, а также сказать мне (с примерами, пожалуйста), как правильно вызывать эту DLL, посылать ей переменные и перехватывать ее возвращаемое значение. Я буду очень благодарен.

Я просмотрел МНОГИЕ посты / статьи и получил кусочки и кусочки, которые завели меня так далеко, но ничего не было все включено.

Я также попробовал это

-- Scratch variables used in the script
DECLARE @retVal INT
DECLARE @comHandle INT
DECLARE @errorSource VARCHAR(8000)
DECLARE @errorDescription VARCHAR(8000)
DECLARE @retString VARCHAR(100)

-- Initialize the COM component.
EXEC @retVal = sp_OACreate 'HTTPDLL.HTTPDLL', @comHandle OUTPUT
IF (@retVal <> 0)
BEGIN
  -- Trap errors if any
  EXEC sp_OAGetErrorInfo @comHandle, @errorSource OUTPUT, @errorDescription OUTPUT
  SELECT [Error Source] = @errorSource, [Description] = @errorDescription
  RETURN
END

(и другие подобные варианты) и получите это в ответе sp_OAGetErrorInfo

"Ошибка Источник Описание ODSOLE Расширенная процедура Недопустимая строка класса"

Возможно, я вызываю это неправильно, но я не смог заставить его работать (всегда возвращаю 'неверную строку класса')

Заранее спасибо за вашу помощь!.

3 ответа

Вы создали сборку CLR, которая отличается от неуправляемой расширенной хранимой процедуры или COM-объекта автоматизации OLE. Вы были на пути к добавлению расширенной хранимой процедуры. Вы не делаете это здесь. Вам необходимо создать хранимую процедуру с использованием синтаксиса CREATE PROCEDURE DDL из сборки. Взгляните на исходные тексты и сценарии создания для моей статьи о SQL Server Central:

http://www.sqlservercentral.com/articles/SQLCLR/65657/

Вам понадобятся права на внешний доступ к сборке, их нельзя создать с помощью SAFE и сделать вызов веб-службы подобным образом. В дополнение к этому, добавление этой функции в качестве триггера - плохая идея. Если есть проблема с веб-сервисом, и вы генерируете необработанное исключение CLR, это может вызвать транзакционный сбой и откат в триггере. В дополнение к этому, если есть задержка в вызове веб-службы, вы задержите завершение транзакции в SQL, что может привести к блокировке и медленному времени отклика.

Лучшим решением для этого было бы использовать службу очереди и уведомления Service Broker с внешним активатором, чтобы активировать внешний процесс для асинхронной работы очереди и вне SQL Server. Все, что нужно сделать триггеру - это отправить сообщение в очередь, и все готово. Таким образом, если имеется задержка в вызове службы или служба не работает, информация все еще сохраняется, и если вы правильно создадите свое приложение активации, оно будет обрабатывать очередь транзакционным способом, поэтому в случае сбоя информация останется в очереди для повторной попытки позже.

Пожалуйста, посмотрите на этот http://dbalink.wordpress.com/2008/10/25/cannot-load-the-dll-error-in-sql-server-2005/

Это, вероятно, то, что вам нужно;-)

ACPerkins @ Experts-exchange просветил нас этой статьей. Худшая практика - запуск внешних событий http://www.sqlservercentral.com/articles/Triggers/worstpracticetriggeringexternalevents/1283/

и поэтому мы в настоящее время изучаем некоторые другие методы. Спасибо за вашу помощь. Энтони

Другие вопросы по тегам