2009-06-29 37 views
7

Tôi tạo ra một hàm vô hướng trong DBLàm thế nào để sử dụng các hàm do người dùng SQL định nghĩa trong .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 

Bây giờ tôi muốn chạy nó trong .NET C# hoặc mã VB.NET.

Tôi sử dụng Khung thực thể, tôi đã cố gắng ánh xạ nó với ánh xạ hàm và tôi đã không thành công. tôi không quan tâm để làm điều đó với DbCommand đơn giản, vấn đề là tôi không nhận được kết quả (chức năng tồn tại trong lớp Entities):

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

Có giải pháp nào? Các bài đăng trong C# hoặc VB.NET sẽ được chào đón.

Trả lời

15

Có vẻ như cách bên phải trong trường hợp này là sử dụng chức năng của khung thực thể để xác định hàm .NET và ánh xạ tới UDF của bạn, nhưng tôi nghĩ tôi thấy lý do bạn không nhận được kết quả bạn mong đợi khi bạn sử dụng ADO.NET để làm điều đó - bạn đang nói rằng bạn đang gọi một thủ tục được lưu trữ, nhưng bạn đang thực sự gọi một hàm.

Hãy thử điều này:

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

Kết quả: SqlException: 'fn_GetUserId_Username' không phải là tên hàm được công nhận. – Shimmy

+3

@Shimmy: chỉ định tên chủ sở hữu, "dbo" -> "chọn dbo.fn_GetUserId_Username (@Username)" – Sung

+0

Điều đó có hiệu quả, cảm ơn! – Shimmy

3

này rất giống với câu trả lời ở trên, nhưng vào mã bên dưới cho phép bạn gọi một UDF với bất kỳ số lượng các thông số và bất kỳ kiểu trả về. Điều này có thể hữu ích như một giải pháp tổng quát hơn. Điều này cũng đã không được kiểm tra kỹ lưỡng ... Tôi nghĩ rằng nó sẽ có một số vấn đề với varchars.

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

Đúng và rực rỡ! Thnx. –

Các vấn đề liên quan