2009-06-29 20 views
7

stworzyłem skalarną funkcję w DBJak korzystać z funkcji zdefiniowanych przez użytkownika SQL w .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 

teraz chcę go uruchomić w moim .NET C# lub VB.NET kodu.

Używam Entity Framework, próbowałem odwzorować go za pomocą mapowania funkcji i nie odniosłem sukcesu. nie obchodzi mnie to zrobić w prosty DbCommand, problemem jest to, że mogę dostać żadnych wyników (funkcja istnieje w klasie podmiotów):

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

Czy istnieje rozwiązanie? Wpisy w C# lub VB.NET będą mile widziane.

Odpowiedz

15

Brzmi jak prawo sposób w tym przypadku jest użycie funkcji struktury encji do zdefiniowania funkcji .NET i mapowania tego do UDF, ale myślę, że rozumiem, dlaczego nie otrzymujesz wyniku można tego oczekiwać, gdy używa się ADO.NET, aby to zrobić - mówisz, że wywołujesz procedurę składowaną, ale tak naprawdę wywołujesz funkcję.

Spróbuj tego:

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

Wynik: SQLException: 'fn_GetUserId_Username' nie jest znana nazwa funkcji. – Shimmy

+3

@Shimmy: określ nazwę właściciela, "dbo" -> "wybierz dbo.fn_GetUserId_Username (@Username)" – Sung

+0

To działało, dziękuję! – Shimmy

3

ta jest bardzo podobna do powyższej odpowiedzi, ale poniżej kod pozwala zadzwonić UDF z dowolnej liczby parametrów i wszelkiego rodzaju powrotnego. Może to być przydatne jako bardziej ogólne rozwiązanie. To też nie zostało dokładnie przetestowane ... Myślę, że będzie to miało pewne problemy z varcharami.

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

Prawidłowe i genialne! Thnx. –

Powiązane problemy