2009-06-29 6 views
7

Ich habe eine skalare Funktion im DBWie SQL benutzerdefinierte Funktionen in .NET zu verwenden?

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[fn_GetUserId_Username] 
    (
    @Username varchar(32) 
    ) 
RETURNS int 
AS 
    BEGIN 
    DECLARE @UserId int 
    SELECT @UserId = UserId FROM [User] WHERE Username = @Username 
    RETURN @UserId 
    END 

Jetzt möchte ich es in meiner .NET C# oder VB.NET-Code auszuführen.

Ich benutze Entity Framework, ich habe versucht, es mit Funktionszuordnung zuordnen, und ich habe keinen Erfolg. i do not care es mit einfachen DbCommand zu tun, ist das Problem, dass ich keine Ergebnisse erhalten (die Funktion in der Entities Klasse vorhanden ist):

public int GetUserIdByUsername(string username) 
{ 
    EntityConnection connection = (EntityConnection)Connection;    
    DbCommand com = connection.StoreConnection.CreateCommand(); 
    com.CommandText = "fn_GetUserId_Username"; 
    com.CommandType = CommandType.StoredProcedure; 
    com.Parameters.Add(new SqlParameter("Username", username)); 
    if (com.Connection.State == ConnectionState.Closed) com.Connection.Open(); 
    try 
    { 
     var result = com.ExecuteScalar(); //always null 
    } 
    catch (Exception e) 
    { 
    } 
    return result; 
} 

Gibt es eine Lösung? Beiträge in C# oder VB.NET werden willkommen sein.

Antwort

15

Es klingt wie die rechts Weise in diesem Fall ist die Funktionalität des Entity-Framework verwenden, um eine .NET-Funktion zu definieren und das auf Ihre UDF zuordnen, aber ich denke, ich sehe, warum Sie das Ergebnis nicht erhalten Sie erwarten, wenn Sie ADO.NET dazu verwenden - Sie sagen, dass Sie eine gespeicherte Prozedur aufrufen, aber Sie rufen wirklich eine Funktion auf.

Try this:

public int GetUserIdByUsername(string username) 
{ 
    EntityConnection connection = (EntityConnection)Connection;    
    DbCommand com = connection.StoreConnection.CreateCommand(); 
    com.CommandText = "select dbo.fn_GetUserId_Username(@Username)"; 
    com.CommandType = CommandType.Text; 
    com.Parameters.Add(new SqlParameter("@Username", username)); 
    if (com.Connection.State == ConnectionState.Closed) com.Connection.Open(); 
    try 
    { 
     var result = com.ExecuteScalar(); // should properly get your value 
     return (int)result; 
    } 
    catch (Exception e) 
    { 
     // either put some exception-handling code here or remove the catch 
     // block and let the exception bubble out 
    } 
} 
+0

Ergebnis: SqlException: 'fn_GetUserId_Username' ist keine anerkannte Funktionsnamen. – Shimmy

+3

@Shimmy: Geben Sie den Namen des Besitzers ein, "dbo" -> "Wählen Sie dbo.fn_GetUserId_Username (@Username)" – Sung

+0

Das hat funktioniert, danke! – Shimmy

3

Dies ist auf die oben genannte Antwort ist sehr ähnlich, aber die folgenden Code können Sie eine benutzerdefinierte Funktion mit einer beliebigen Anzahl von Parametern aufrufen und jede Rückgabetyp. Dies könnte als eine allgemeinere Lösung nützlich sein. Dies wurde auch nicht gründlich getestet ... Ich denke, es wird einige Probleme mit Varchars haben.

internal static T1 CallUDF<T1>(string strUDFName, params SqlParameter[] aspParameters) 
{ 
    using (SqlConnection scnConnection = GetConnection()) 
    using (SqlCommand scmdCommand = new SqlCommand(strUDFName, scnConnection)) 
    { 
     scmdCommand.CommandType = CommandType.StoredProcedure; 

     scmdCommand.Parameters.Add("@ReturnValue", TypeToSqlDbType<T1>()).Direction = ParameterDirection.ReturnValue; 
     scmdCommand.Parameters.AddRange(aspParameters); 

     scmdCommand.ExecuteScalar(); 

     return (T1) scmdCommand.Parameters["@ReturnValue"].Value; 
    } 
} 

private static SqlDbType TypeToSqlDbType<T1>() 
{ 
    if (typeof(T1) == typeof(bool)) 
    { 
     return SqlDbType.Bit; 
    } 
     . 
     . 
     . 
    else 
    { 
     throw new ArgumentException("No mapping from type T1 to a SQL data type defined."); 
    } 
} 
+0

Proper und brilliant! Thnx. –