2009-06-29 17 views
7

creé una función escalar en el PP¿Cómo usar las funciones SQL definidas por el usuario en .NET?

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 

Ahora quiero ejecutarlo dentro de mi .NET C# o VB.NET código.

Uso Entity Framework, traté de mapearlo con el mapeo de funciones y no tuve éxito. no me importa hacerlo con sencillo DbCommand, el problema es que no da resultados positivos (la función existe en la clase de Entidades):

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; 
} 

¿Hay alguna solución? Publicaciones en C# o VB.NET serán bienvenidas.

Respuesta

15

Parece que el derecho en este caso es utilizar la funcionalidad de la entidad marco para definir una función .NET y asignarla a su UDF, pero creo que veo por qué no obtiene el resultado Cuando utilizas ADO.NET, esperas que estés llamando a un procedimiento almacenado, pero realmente estás llamando a una función.

Prueba esto:

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

Resultado: SqlException: 'fn_GetUserId_Username' no es un nombre de función reconocida. – Shimmy

+3

@Shimmy: especifique el nombre del propietario, "dbo" -> "seleccione dbo.fn_GetUserId_Username (@Username)" – Sung

+0

¡Eso funcionó, gracias! – Shimmy

3

Esto es muy similar a la respuesta anterior, pero el código de abajo le permite llamar a una UDF con cualquier número de parámetros y cualquier tipo de retorno. Esto podría ser útil como una solución más general. Esto tampoco ha sido probado a fondo ... Creo que tendrá algunos problemas con varchar.

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

¡Adecuado y brillante! Thnx. –

Cuestiones relacionadas