Bartłomiej W.

Bartłomiej W. Senior Software
Engineer, Cegedim
Group Poland Sp. z
o.o.

Temat: Wykorzystanie DLL w procedurach opartych na środowisku CLR

Witam,

mam mały problem.

chciałbym mieć dostęp z poziomu MS SQL 2005 do funkcji znajdujących się w bibliotece MyDLL.dll (dla przykładu: funkcja int add (int i, int j) ).
W tym celu użyłem mechanizmu CLR, tworząc odpowiednią bibliotekę CLR o nazwie MyCLR.dll, zawierającą funkcję int add (int i, int j).
Po zarejestrowaniu assembly i storedProcedure w MS SQL wszystko działa w przpadku gdy sam napiszę w MyCLR funkcję add jako np return i + j.
Problem: czy i jak mogę wykorzystać w MyCLR.dll funkcję add z MyDLL.dll.

w projekcie MyCLR ustawiłem Common Language Runtime Support jako /clr: pure,
Assembly Permision Level jako UNSAFE.

w MyCLR próbuję odwołać się do MyDLL przez (w uproszczeniu pomijam obsługę ewentualnych błędów):
...
...
[Microsoft::SqlServer::Server::SqlProcedure]
static int add(int i, int j)
{
typedef int (*CALLBACK LPFNDLLFUNC1)(int,int);
HINSTANCE hDLL = NULL; // Handle to DLL
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer

hDLL = LoadLibrary(L"MyDLL.dll");

lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,"add");
int i = lpfnDllFunc1(4,6);
return i;
}

w MS SQL rejestruję jako:
CREATE ASSEMBLY assembly_add
FROM 'c:\_clr\Proj.dll'
WITH PERMISSION_SET = UNSAFE
go

CREATE PROCEDURE MyStoredProc @i int, @j int
AS EXTERNAL NAME assembly_add.[add].MyStoredProc

do tej pory wszystko przebiega pomyślnie, jednak gdy wywołuję procedurę:
declare @w int
exec @w = MyStoredProc 6,2

print @w

pojawia się błąd:
Msg 6522, Level 16, State 1, Procedure MyStoredProc, Line 0
A .NET Framework error occurred during execution of user-defined routine or aggregate "MyStoredProc": .

Temat: Wykorzystanie DLL w procedurach opartych na środowisku CLR

Hej, koniecznie te funkcje muszą się znajdować w "zewnętrznym" pliku DLL?

Bo jest prostszy sposób, utwór projekt w Visual Studio: Visual C#/Database/SQL Server Project. W oknie Solution Explorer dodaj User-Defined Function napisz tam odpowiedni kod. Uruchom projekt i tyle, visual studio samo zrobi Deploy.
Bartłomiej W.

Bartłomiej W. Senior Software
Engineer, Cegedim
Group Poland Sp. z
o.o.

Temat: Wykorzystanie DLL w procedurach opartych na środowisku CLR

Właśnie chodzi o to, że w tej "zewnętrznej" dll mam zbiór metod, które coś robią, ale nie ma to dla mnie znaczenia co. Mnie interesuje tylko podanie parametrów do tych metod a otrzymany wynik dalej przetwarzać. Najprościej by było napisać samemu, ale tutaj nie bardzo jest taka możliwość.
Krzysztof Mierzejewski

Krzysztof Mierzejewski SharePoint
Consultant

Temat: Wykorzystanie DLL w procedurach opartych na środowisku CLR

Ten wyjątek, który wymieniłeś, niewiele mówi. Potrzebny będzie inner exception, inaczej nie dowiemy się, co się naprawdę dzieje...

Co do dynamicznego ładowania assembly w hoście SQL Servera, jest ograniczenie - nie możesz ładować assembly, które nie jest skatalogowane w hoście, niezależnie od Permission Level (System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.). Poza tym nie ma najmniejszego problemu, jak będziesz miał obie assembly dodane do katalogu (caller i callee) możesz użyć np. Assembly.Load (pamiętaj, aby podać full qualified name). Permission Level obu blibliotek może być spokojnie Safe.

U mnie to wygląda tak:

Callee:
namespace Test.ExternalAssembly
{
public static class ExternalClass
{
private static readonly Random _random = new Random();

public static int GetRandomInteger()
{
return _random.Next(1, 10);
}
}
}


Caller:
public static class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 ReturnInteger()
{
Assembly external = Assembly.Load(@"Test.ExternalAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
Type externalType = external.GetType("Test.ExternalAssembly.ExternalClass");
MethodInfo externalMethod = externalType.GetMethod("GetRandomInteger", BindingFlags.Static | BindingFlags.Public);
return new SqlInt32((int)externalMethod.Invoke(null, null));
}
}

Temat: Wykorzystanie DLL w procedurach opartych na środowisku CLR

MyDLL.dll to biblioteka z kodem natywnym? Ładujesz przez LoadLibrary i GetProcAddress więc zakładam, że tak jest.

Pierwsze co mi się nasuwa, to sprawdzenie, czy działasz z wersją SQL Server-a 64 czy 32 bit i na jaką architekturę jest skompilowana MyDLL.dll

Jak są to rożne architektury, to może być problem.

Jeśli jest zgodność, to można by spróbować skorzystać ze starego mechanizmu procedur rozszerzonych (bez CLR). Co prawda metoda ta jest oznaczona jako przestarzała, ale na 2005 będzie działałoMichał Piaskowski edytował(a) ten post dnia 13.11.09 o godzinie 23:04

Następna dyskusja:

Statystyki - NET CLR?




Wyślij zaproszenie do