Wednesday, March 21, 2012
Problem freeing resources used by SQLPrimaryKeys
First of all, I'm a little inexperienced with the odbc32.dll API's and
not too familiar with all the details of their usage. I have a list of
tables in the database and I'm iterating over that list and building
the primary key for each table. When I perform the iteration my
machine's memory usage spikes and the memory is never released (until
the program ends, of course). If I run the process several times the
memory usage becomes so high that the program crashes. I know that it's
not from creating objects in the application because I removed the code
that instantiates them and it still performed the same. Basically, I
reduced the algorithm to just the code that uses the odbc32.dll API's.
Below is the general code I'm using for each table in one iteration.
Can anyone tell me what I'm doing wrong and if there's any way to
correct it?
Thanks in advance,
Shannon
// Declare all the variables
res = SQLAllocEnv( ref env );
res = SQLAllocConnect( env, ref hdbc );
res = SQLConnect( hdbc.ToInt32(), dsnName, SQL_NTS, user, ( short
)( user == null ? 0 : user.Length ), pwd, ( short )( pwd == null ? 0 :
pwd.Length ) );
res = SQLAllocHandle( SQL_HANDLE_STMT, hdbc.ToInt32(), ref hstmt
);
res = SQLPrimaryKeys( hstmt.ToInt32(), null, SQL_NTS, schema, (
short )( schema == null ? 0 : schema.Length ), tableName, ( short
)tableName.Length );
res = SQLFetch( hstmt.ToInt32() );
while( res == 0 )
{
SQLGetData( hstmt.ToInt32(), 1, SQL_CHAR, szCatalog,
MAX_FIELDSIZE, ref lCatalog );
SQLGetData( hstmt.ToInt32(), 2, SQL_CHAR, szSchema,
MAX_FIELDSIZE, ref lSchema );
SQLGetData( hstmt.ToInt32(), 3, SQL_CHAR, szTableName,
MAX_FIELDSIZE, ref lTableName );
SQLGetData( hstmt.ToInt32(), 4, SQL_CHAR, szColumnName,
MAX_FIELDSIZE, ref lColumnName );
SQLGetData( hstmt.ToInt32(), 5, SQL_SMALLINT, szColumnSequence,
MAX_FIELDSIZE, ref lColumnSequence );
SQLGetData( hstmt.ToInt32(), 6, SQL_CHAR, szPKName,
MAX_FIELDSIZE, ref lPKName );
// Create application objects from primary key data
res = SQLFetch( hstmt.ToInt32() );
}
res = SQLCloseCursor( hstmt.ToInt32() );
res = SQLFreeHandle( SQL_HANDLE_STMT, hstmt.ToInt32() );
res = SQLFreeHandle( SQL_HANDLE_DBC, hdbc.ToInt32() );
res = SQLFreeHandle( SQL_HANDLE_ENV, env );
res = SQLDisconnect( hdbc.ToInt32() );Okay, after all the hair pulling, wouldn't it figure that the minute I
post a question I figure it out. In the cleanup process, I call
SQLFreeHandle on hdbc before I call SQLDisconnect on it. You must
disconnect first.
Wednesday, March 7, 2012
Problem Creating Stored Procedure From A Library, DLL
I'm having a problem creating Stored Procedure from a library I have created. I have found that the Create Assembly query causes the Assemby to be placed into the Master Database's Assembly collection. The other is that the Create Procedure Query states that it cannot find the type in the assembly. Can someone see what is going on and let me know
I have also changed the "struct" to a "class" and I get the same error message.
I've included the code snippit, and queries belows:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data.SqlTypes;
namespace HHLibrary
{
[Serializable]
public struct State
{
[SqlFunction(Name = "GetStateIndexByName",
IsDeterministic = true,
DataAccess = DataAccessKind.Read)]
public static SqlInt32 GetStateIndexByName(SqlString Name, out SqlByte StateIndex)
{
SqlInt32 iResult = 0;
StringBuilder sb = new StringBuilder(500);
SqlCommand command = new SqlCommand();
StateIndex = 255; // Set the output parameter to an illegal value
. . .
return iResult;
}
}
}
************************ Compilation Messages ******************************************
Build started: Project: HeadHunterLibrary, Configuration: Debug Any CPU
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /debug+ /debug:full /optimize- /out:obj\Debug\HeadHunterLibrary.dll /target:library State.cs Properties\AssemblyInfo.cs
Compile complete -- 0 errors, 0 warnings
HeadHunterLibrary -> C:\HHLibraries\HeadHunterLibrary.dll
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
************************ Trans-SQL Query ******************************************
create assembly HeadHunterLibrary
FROM 'C:\HHLibraries\HeadHunterLibrary.dll'
WITH PERMISSION_SET = SAFE;
GO
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint
)
AS EXTERNAL NAME HeadHunterLibrary.State.GetStateIndexByName;
GO
************************ Messages From Executing The Query ************************************
Msg 6505, Level 16, State 1, Procedure GetStateIndexByName, Line 2
Could not find Type 'State' in assembly 'HeadHunterLibrary'.
You need to specify the database in use. CREATE ASSEMBLY add assemblies to the database in use. For example:
use MyDatabase
create assembly HeadHunterLibrary
FROM 'C:\HHLibraries\HeadHunterLibrary.dll'
WITH PERMISSION_SET = SAFE;
GO
You can double check that it worked by:
SELECT * from myDatabase.sys.assemblies
You need to square bracket the namespace.class. As was written thinks HeadHunterLibrary is a database name. For example:
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
Dan
Made the corrections you recommended. Still have one problem that I don’t understand. The query I execute to create the stored procedure is:
USE HeadHunter
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint OUTPUT
)
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
When I execute the Create Procedure dbo.GetStateIndexByName I get the following error message.
Msg 102, Level 15, State 1, Procedure GetStateIndexByName, Line 5 Incorrect syntax near ';'.
The managed code looks like this:
namespace HeadHunterLibrary
{
[Serializable]
public class State
{
public static SqlInt32 GetStateIndexByName(SqlString Name, out SqlByte StateIndex)
{
. . .
}
}
}
Can you see what is causing the error?
Thank You
Dan Marks
Logos-Systems@.mchsi.com
|||Made the corrections you recommended. Still have one problem that I don’t understand. The query I execute to create the stored procedure is:
USE HeadHunter
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint OUTPUT
)
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
When I execute the Create Procedure dbo.GetStateIndexByName I get the following error message.
Msg 102, Level 15, State 1, Procedure GetStateIndexByName, Line 5 Incorrect syntax near ';'.
The managed code looks like this:
namespace HeadHunterLibrary
{
[Serializable]
public class State
{
public static SqlInt32 GetStateIndexByName(SqlString Name, out SqlByte StateIndex)
{
. . .
}
}
}
Can you see what is causing the error?
Thank You
Dan Marks
Logos-Systems@.mchsi.com
|||Made the corrections you recommended. Still have one problem that I don’t understand. The query I execute to create the stored procedure is:
USE HeadHunter
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint OUTPUT
)
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
When I execute the Create Procedure dbo.GetStateIndexByName I get the following error message.
Msg 102, Level 15, State 1, Procedure GetStateIndexByName, Line 5 Incorrect syntax near ';'.
The managed code looks like this:
namespace HeadHunterLibrary
{
[Serializable]
public class State
{
public static SqlInt32 GetStateIndexByName(SqlString Name, ref SqlByte StateIndex)
{
. . .
}
}
}
Can you see what is causing the error?
Thank You
Dan Marks
Logos-Systems@.mchsi.com
|||I see several problems.
The error is probably caused by the lack of assembly name in:
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
Try this:
AS EXTERNAL NAME [AssemblyName].[HeadHunterLibrary.State].GetStateIndexByName;
You are also missing a return value (your procedure returns a SqlInt32, but you don't specify that in the stored procedure definition).
Finally, you don't have a StoredProcedure attribute on your method, put this on the line before the method:
[Microsoft.SqlServer.Server.SqlProcedure]
Hope this helps.
|||Namespace problem?
CREATE PROCEDURE hello
AS
EXTERNAL NAME HelloWorld.StoredProcedures.HelloWorld
GO
EXEC hello
Msg 6505, Level 16, State 1, Procedure hello, Line 1
Could not find Type 'StoredProcedures' in assembly 'HelloWorld'.
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'hello'.
CREATE PROCEDURE hello
AS
EXTERNAL NAME HelloWorld.[HelloWorld.StoredProcedures].HelloWorld
GO
EXEC hello
Hello world! It's now 18/04/2007 14:26:23
try something like:
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint
)
AS EXTERNAL NAME HeadHunterLibrary.[HHLibrary.State].GetStateIndexByName;
GO
Problem Creating Stored Procedure From A Library, DLL
I'm having a problem creating Stored Procedure from a library I have created. I have found that the Create Assembly query causes the Assemby to be placed into the Master Database's Assembly collection. The other is that the Create Procedure Query states that it cannot find the type in the assembly. Can someone see what is going on and let me know
I have also changed the "struct" to a "class" and I get the same error message.
I've included the code snippit, and queries belows:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data.SqlTypes;
namespace HHLibrary
{
[Serializable]
public struct State
{
[SqlFunction(Name = "GetStateIndexByName",
IsDeterministic = true,
DataAccess = DataAccessKind.Read)]
public static SqlInt32 GetStateIndexByName(SqlString Name, out SqlByte StateIndex)
{
SqlInt32 iResult = 0;
StringBuilder sb = new StringBuilder(500);
SqlCommand command = new SqlCommand();
StateIndex = 255; // Set the output parameter to an illegal value
. . .
return iResult;
}
}
}
************************ Compilation Messages ******************************************
Build started: Project: HeadHunterLibrary, Configuration: Debug Any CPU
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Csc.exe /noconfig /nowarn:1701,1702 /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /debug+ /debug:full /optimize- /out:obj\Debug\HeadHunterLibrary.dll /target:library State.cs Properties\AssemblyInfo.cs
Compile complete -- 0 errors, 0 warnings
HeadHunterLibrary -> C:\HHLibraries\HeadHunterLibrary.dll
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
************************ Trans-SQL Query ******************************************
create assembly HeadHunterLibrary
FROM 'C:\HHLibraries\HeadHunterLibrary.dll'
WITH PERMISSION_SET = SAFE;
GO
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint
)
AS EXTERNAL NAME HeadHunterLibrary.State.GetStateIndexByName;
GO
************************ Messages From Executing The Query ************************************
Msg 6505, Level 16, State 1, Procedure GetStateIndexByName, Line 2
Could not find Type 'State' in assembly 'HeadHunterLibrary'.
You need to specify the database in use. CREATE ASSEMBLY add assemblies to the database in use. For example:
use MyDatabase
create assembly HeadHunterLibrary
FROM 'C:\HHLibraries\HeadHunterLibrary.dll'
WITH PERMISSION_SET = SAFE;
GO
You can double check that it worked by:
SELECT * from myDatabase.sys.assemblies
You need to square bracket the namespace.class. As was written thinks HeadHunterLibrary is a database name. For example:
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
Dan
Made the corrections you recommended. Still have one problem that I don’t understand. The query I execute to create the stored procedure is:
USE HeadHunter
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint OUTPUT
)
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
When I execute the Create Procedure dbo.GetStateIndexByName I get the following error message.
Msg 102, Level 15, State 1, Procedure GetStateIndexByName, Line 5 Incorrect syntax near ';'.
The managed code looks like this:
namespace HeadHunterLibrary
{
[Serializable]
public class State
{
public static SqlInt32 GetStateIndexByName(SqlString Name, out SqlByte StateIndex)
{
. . .
}
}
}
Can you see what is causing the error?
Thank You
Dan Marks
Logos-Systems@.mchsi.com
|||Made the corrections you recommended. Still have one problem that I don’t understand. The query I execute to create the stored procedure is:
USE HeadHunter
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint OUTPUT
)
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
When I execute the Create Procedure dbo.GetStateIndexByName I get the following error message.
Msg 102, Level 15, State 1, Procedure GetStateIndexByName, Line 5 Incorrect syntax near ';'.
The managed code looks like this:
namespace HeadHunterLibrary
{
[Serializable]
public class State
{
public static SqlInt32 GetStateIndexByName(SqlString Name, out SqlByte StateIndex)
{
. . .
}
}
}
Can you see what is causing the error?
Thank You
Dan Marks
Logos-Systems@.mchsi.com
|||Made the corrections you recommended. Still have one problem that I don’t understand. The query I execute to create the stored procedure is:
USE HeadHunter
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint OUTPUT
)
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
When I execute the Create Procedure dbo.GetStateIndexByName I get the following error message.
Msg 102, Level 15, State 1, Procedure GetStateIndexByName, Line 5 Incorrect syntax near ';'.
The managed code looks like this:
namespace HeadHunterLibrary
{
[Serializable]
public class State
{
public static SqlInt32 GetStateIndexByName(SqlString Name, ref SqlByte StateIndex)
{
. . .
}
}
}
Can you see what is causing the error?
Thank You
Dan Marks
Logos-Systems@.mchsi.com
|||I see several problems.
The error is probably caused by the lack of assembly name in:
AS EXTERNAL NAME [HeadHunterLibrary.State].GetStateIndexByName;
Try this:
AS EXTERNAL NAME [AssemblyName].[HeadHunterLibrary.State].GetStateIndexByName;
You are also missing a return value (your procedure returns a SqlInt32, but you don't specify that in the stored procedure definition).
Finally, you don't have a StoredProcedure attribute on your method, put this on the line before the method:
[Microsoft.SqlServer.Server.SqlProcedure]
Hope this helps.
|||Namespace problem?
CREATE PROCEDURE hello
AS
EXTERNAL NAME HelloWorld.StoredProcedures.HelloWorld
GO
EXEC hello
Msg 6505, Level 16, State 1, Procedure hello, Line 1
Could not find Type 'StoredProcedures' in assembly 'HelloWorld'.
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'hello'.
CREATE PROCEDURE hello
AS
EXTERNAL NAME HelloWorld.[HelloWorld.StoredProcedures].HelloWorld
GO
EXEC hello
Hello world! It's now 18/04/2007 14:26:23
try something like:
CREATE PROCEDURE dbo.GetStateIndexByName
( @.Name nvarchar(25),
@.StateIndex tinyint
)
AS EXTERNAL NAME HeadHunterLibrary.[HHLibrary.State].GetStateIndexByName;
GO
Saturday, February 25, 2012
Problem creating a function from an assembly
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlTypes
Public Class SICTrans
Public Shared Function TransSIC(ByVal inpSIC As String) As String
'Dim conn As SqlConnection = New SqlConnection("context connection=true")
Dim NewSIC, TempSIC, tempFSIC As String
If Len(NZ(inpSIC)) > 0 Then
TempSIC = NZ(inpSIC)
If Len(TempSIC) < 5 Then TempSIC = Left("00000", 5 - Len(TempSIC))
tempFSIC = Left(TempSIC, 2) + "." + Mid(TempSIC, 3, 2)
If Val(Right(TempSIC, 1)) > 0 Then
tempFSIC = tempFSIC + "/" + Right(TempSIC, 1)
End If
End If
NewSIC = tempFSIC
TransSIC = NewSIC
End Function
Public Shared Function NZ(ByVal input As String) As String
If Not (input Is Nothing) Then
Return input
Exit Function
End If
Return String.Empty
End Function
End Class
Which compiles fine...
i then use the following code to create the assembly in SQL which is fine:
USE NARD
GO
CREATE ASSEMBLY SICCodeTrans
FROM 'c:\SICCodeTrans.dll'
WITH PERMISSION_SET = SAFE
GO
but when i goto create the function with the following code it wont have it!
CREATE FUNCTION TransSICCode(@.inpSIC varchar)
RETURNS varchar
AS EXTERNAL NAME
SICCodeTrans.SICTrans.TransSIC
GO
It gives me the following error message
Msg 6505, Level 16, State 1, Procedure TransSICCode, Line 1
Could not find Type 'SICTrans' in assembly 'SICCodeTrans'.
Any ideas?
Thanks
Marek Kluczynski
I think what's going on here is that there is a root namespace on the project.
IIRC, in a C# project VS will simply insert the root namespace delcaration into your code when you use certain templates. In VB, on the other hand, the compiler decides to insert the namespace definition without having it show up in the code.
When you go to create the function in SQL, it can't find it because there is no SICTrans class in the default namespace, there is a SICTrans class in whatever root namespace was set on the project.
You can right-click on the project in VS and pull up the propertiesunder the "Application" tab you'll see this.
Assuming your namespace is NAMESPACE, you'd think you could do the following:
CREATE FUNCTION TransSICCode(@.inpSIC varchar)
RETURNS varchar
AS EXTERNAL NAME
SICCodeTrans.NAMESPACE.SICTrans.TransSIC
GO
This won't workit's a (rather annoying) syntax error. You have to write it like this:
CREATE FUNCTION TransSICCode(@.inpSIC varchar)
RETURNS varchar
AS EXTERNAL NAME
SICCodeTrans.[NAMESPACE.SICTrans].TransSIC
GO
Hope this works for you. Let us know. :)
Cheers
-Isaac
yes this seems to have resolved the namespace error.
I now have the following error:
Msg 6551, Level 16, State 2, Procedure TransSICCode, Line 1
CREATE FUNCTION for "TransSICCode" failed because T-SQL and CLR types for return value do not match.
Many thanks
Marek
|||I suspect two things. First, you should map the string to an nvarchar, not a varcharCLR strings are Unicode. Second, you need to give a parameter to the nvarchar, e.g., nvarchar(4000), nvarchar(max), etc.Cheers,
-Isaac|||Many thanks for all your help
Problem creating a function from an assembly
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlTypes
Public Class SICTrans
Public Shared Function TransSIC(ByVal inpSIC As String) As String
'Dim conn As SqlConnection = New SqlConnection("context connection=true")
Dim NewSIC, TempSIC, tempFSIC As String
If Len(NZ(inpSIC)) > 0 Then
TempSIC = NZ(inpSIC)
If Len(TempSIC) < 5 Then TempSIC = Left("00000", 5 - Len(TempSIC))
tempFSIC = Left(TempSIC, 2) + "." + Mid(TempSIC, 3, 2)
If Val(Right(TempSIC, 1)) > 0 Then
tempFSIC = tempFSIC + "/" + Right(TempSIC, 1)
End If
End If
NewSIC = tempFSIC
TransSIC = NewSIC
End Function
Public Shared Function NZ(ByVal input As String) As String
If Not (input Is Nothing) Then
Return input
Exit Function
End If
Return String.Empty
End Function
End Class
Which compiles fine...
i then use the following code to create the assembly in SQL which is fine:
USE NARD
GO
CREATE ASSEMBLY SICCodeTrans
FROM 'c:\SICCodeTrans.dll'
WITH PERMISSION_SET = SAFE
GO
but when i goto create the function with the following code it wont have it!
CREATE FUNCTION TransSICCode(@.inpSIC varchar)
RETURNS varchar
AS EXTERNAL NAME
SICCodeTrans.SICTrans.TransSIC
GO
It gives me the following error message
Msg 6505, Level 16, State 1, Procedure TransSICCode, Line 1
Could not find Type 'SICTrans' in assembly 'SICCodeTrans'.
Any ideas?
Thanks
Marek Kluczynski
I think what's going on here is that there is a root namespace on the project.
IIRC, in a C# project VS will simply insert the root namespace delcaration into your code when you use certain templates. In VB, on the other hand, the compiler decides to insert the namespace definition without having it show up in the code.
When you go to create the function in SQL, it can't find it because there is no SICTrans class in the default namespace, there is a SICTrans class in whatever root namespace was set on the project.
You can right-click on the project in VS and pull up the propertiesunder the "Application" tab you'll see this.
Assuming your namespace is NAMESPACE, you'd think you could do the following:
CREATE FUNCTION TransSICCode(@.inpSIC varchar)
RETURNS varchar
AS EXTERNAL NAME
SICCodeTrans.NAMESPACE.SICTrans.TransSIC
GO
This won't workit's a (rather annoying) syntax error. You have to write it like this:
CREATE FUNCTION TransSICCode(@.inpSIC varchar)
RETURNS varchar
AS EXTERNAL NAME
SICCodeTrans.[NAMESPACE.SICTrans].TransSIC
GO
Hope this works for you. Let us know. :)
Cheers
-Isaac
yes this seems to have resolved the namespace error.
I now have the following error:
Msg 6551, Level 16, State 2, Procedure TransSICCode, Line 1
CREATE FUNCTION for "TransSICCode" failed because T-SQL and CLR types for return value do not match.
Many thanks
Marek
|||I suspect two things. First, you should map the string to an nvarchar, not a varcharCLR strings are Unicode. Second, you need to give a parameter to the nvarchar, e.g., nvarchar(4000), nvarchar(max), etc.Cheers,
-Isaac|||Many thanks for all your help