从 SQL Server 中检索各种存储过程的数据的单一方法,如何处理参数?

Posted

技术标签:

【中文标题】从 SQL Server 中检索各种存储过程的数据的单一方法,如何处理参数?【英文标题】:Singular method to retrieve data from SQL Server for various stored procedures, how to handle parameters? 【发布时间】:2021-10-17 00:39:33 【问题描述】:

我的 SQL 助手类有一个方法,以及一个接受参数的重载:

public static DataTable GetData(string cmd_text)

    DataTable dt = new DataTable();

    SqlConnection conn = GetSqlConnection();

    SqlCommand cmd = new SqlCommand
    
        CommandText = cmd_text,
        CommandType = CommandType.StoredProcedure,
        Connection = conn
    ;

    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
    
        da.Fill(dt);
    

    return dt;

重载:

public static DataTable GetData(string cmd_text, string p1)

    DataTable dt = new DataTable();

    SqlConnection conn = GetSqlConnection();

    SqlCommand cmd = new SqlCommand
    
        CommandText = cmd_text,
        CommandType = CommandType.StoredProcedure,
        Connection = conn
    ;

    //add parameter here somehow?

    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
    
        da.Fill(dt);
    

    return dt;

但是,我在中途突然想到,我需要传递存储过程所期望的相同参数名称。我总是可以通过在我的方法中为参数名称添加另一个参数来解决这个问题,甚至可以通过将 SQL Server 中的参数调整为在我的所有存储过程上都相同,但我想知道这是否可以以另一种方式处理,在 C# 或 SQL 端。

我关于如何实现这一点的理论是构建一个可以调用其他存储过程的包装存储过程,但我不完全确定如果可能的话如何实现。

【问题讨论】:

而你总是只有一个字符串类型的参数?从来没有其他数据类型不超过一个参数? 参数从哪里来?如果 SP 正在“寻找”参数,您可以使用 cmd.Parameters.Add(...) 设置它们。 使用IDictionary<string,object> p,其中键是参数名称,对象是值。 【参考方案1】:

第0步:停止使用DataTable

第 1 步:使用 Dapper

没有第 2 步。

简单地说:

string bar = "ABC"; // just to show usage
var data = connection.Query<YourPoco>(
    "SomeSpName",
    new  foo = 12, bar , // named args
    commandType: CommandType.StoredProcedure).AsList();

【讨论】:

@Austin 它适用于存储过程,如示例所示,因此:如果您更喜欢该路线,那仍然可以【参考方案2】:

使用IDictionary&lt;string,object&gt; p,其中键是参数名称,对象是值。

public static DataTable GetData(string cmd_text, IDictionary<string, object> p1)

    DataTable dt = new DataTable();

    SqlConnection conn = GetSqlConnection();
    SqlCommand cmd = new SqlCommand
    
        CommandText = cmd_text,
        CommandType = CommandType.StoredProcedure,
        Connection = conn
    ;

    
    foreach (var p in p1)
    
        //add parameter here
    

    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
    
        da.Fill(dt);
    

    return dt;

【讨论】:

【参考方案3】:

以及你可以做什么的想法:

在程序启动时查询所有 sp 和属于 sp 的所有参数 在某处缓存它们 在调用 sp 之前从缓存中获取参数并调整您的 SqlCommand

这里是从数据库中获取信息的查询

SELECT 
   SCHEMA_NAME(SCHEMA_ID) AS [Schema]
  ,SO.name AS [ObjectName]             
  ,SO.Type_Desc AS [ObjectType]
  ,P.parameter_id AS [ParameterID]
  ,P.name AS [ParameterName]
  ,TYPE_NAME(P.user_type_id) AS [ParameterDataType]
  ,P.max_length AS [ParameterMaxBytes]
  ,P.is_output AS [IsOutPutParameter]
FROM sys.objects AS SO
INNER JOIN sys.parameters AS P ON SO.OBJECT_ID = P.OBJECT_ID
ORDER BY [Schema], SO.name, P.parameter_id

(但是我认为这不会让你在某些时候走得更远,你需要不止一个参数和其他数据类型和花哨的东西。 我会使用 EF 或按照 Marc Dapper 的建议。 DataSet 和 Friends 的时代结束了。)

【讨论】:

@Austin 看看 Marc 的回答。我认为这是最好的选择。

以上是关于从 SQL Server 中检索各种存储过程的数据的单一方法,如何处理参数?的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 和存储过程从 SQL Server 检索 VarChar(MAX)

如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?

5.SQL Server 2008 数据库

无法从存储过程显示文本到 textview - Android SQL Server

如何在 SQL Server 2008 中检索已删除的存储过程、函数、表

SQL Server检索存储过程的结果集