【问题标题】:I am trying to fetch Datetime attribute from SQL SERVER.SSMS using stored procedure and trying to assign dateofopening variable我正在尝试使用存储过程从 SQL SERVER.SSMS 获取 Datetime 属性并尝试分配 dateofopening 变量
【发布时间】:2021-04-10 11:43:16
【问题描述】:
public void SearchAccount(int accountno,out DateTime dateofopening)
{
    conn = ConnectionEstablisher.getconnection();
    conn.Open();
    cmd = new SqlCommand("account_search", conn);//account_search - stored procedure name
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@accountno", accountno);//searching account no in table
            
    cmd.Parameters.Add(new SqlParameter("@dateofopening",SqlDbType.DateTime));
    cmd.Parameters["@dateofopening"].Direction = ParameterDirection.Output; 
            
    object v = cmd.Parameters[parameterName: dateofopening];
    dateofopening = (datetime)v;

    return;
} 
create proc [dbo].[account_search]  //stored procedure in ssms
    @accountno int,
    @dateofopening datetime output
as
begin 
    select 
        @dateofopening = DateOfOpening 
    from Accounts 
    where AccountNo=@accountno
end

错误:未处理的异常:System.InvalidCastException:指定的转换无效。 在 C:\Users\RAHUL\source\repos\ConsoleApp7\AccountOperations.cs:line 94 中的 ConsoleApp7.AccountOperations.SearchAccount(DateTime& dateofopening) 处

【问题讨论】:

  • 在开始处理输出之前,您在哪里执行命令?我看到您打开了一个连接,并设置了一些参数,但是 SQL Server 什么时候会看到该命令?也请不要使用AddWithValue():blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…
  • 错误:未处理的异常:System.InvalidCastException:无法将“System.Data.SqlClient.SqlParameter”类型的对象转换为“System.IConvertible”类型。在 System.Convert.ToInt32(对象值)
  • DBNull.Value 不是日期时间。检查v == DBNull.Value

标签: c# sql-server visual-studio ssms


【解决方案1】:

dateofopening= Convert.ToDateTime(cmd.Parameters["@dateofopening"].Value.ToString());

【讨论】:

    【解决方案2】:

    该代码中有几个大问题。我在下面发布了修复,cmets 解释了这些变化。

    但重要的是查询永远不会运行。您必须通过 DataAdapter 调用 ExecuteReader()ExecuteScalar()ExectueNonQuery()Fill(),才能在服务器上实际运行查询。

    //functions should accept inputs and return outputs.
    public DateTime SearchAccount(int accountno)
    {
        object result = null;
    
        // Only get the STRING, not the actual connection!
        var connectionString = ConnectionEstablisher.getConnectionString();
    
        // You should create a **brand new connection object** for most queries. Really!
        using (var conn = new SqlConnection(connectionString))
        using (var cmd = new SqlCommand("account_search", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;
    
            //Don't use AddWithValue()! It can really hurt performance if you're not careful.
            cmd.Parameters.Add("@accountno", SqlDbType.Int).Value = accountno;
    
            //Wait as long as possible to open connection, let it close as early as possible
            conn.Open();
    
            //Actually **run the query!**
            result = cmd.ExecuteScalar();
        } //end of the using block guarantees the connection will close, **even if an exception is thrown**
    
        //check for both null (no records returned from dB) and DBNull (NULL value returned from DB)
        if (result == null || result == DBNull.Value) return default(DateTime);
    
        //result ALREADY is a DateTime, so just cast to tell the compiler. Don't use an expensive conversion
        return (DateTime)result;
    }
    

    当然,您还必须将调用代码更改为现在接受(并检查)此函数的结果。

    下面是修改后的 SQL:

    create proc [dbo].[account_search]  //stored procedure in ssms
        @accountno int
    as
    begin 
        select DateOfOpening 
        from Accounts 
        where AccountNo=@accountno
    end
    

    现在我将再次列出 C#,但没有所有额外的 cmets,因此您可以看到它不再是真的:

    public DateTime SearchAccount(int accountno)
    {
        object result = null;
    
        var connectionString = ConnectionEstablisher.getConnectionString();
        using (var conn = new SqlConnection(connectionString))
        using (var cmd = new SqlCommand("account_search", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@accountno", SqlDbType.Int).Value = accountno;
    
            conn.Open();
            result = cmd.ExecuteScalar();
        } 
        if (result == null || result == DBNull.Value) return default(DateTime);
        return (DateTime)result;
    }
    

    如果我们也将 SQL 结构化为 nullDBNull,我们可以进一步简化代码,但实际上不太可能

    作为奖励,这里有一个链接可以帮助解释为什么您不应该尝试在整个应用程序中重复使用连接对象:

    https://softwareengineering.stackexchange.com/questions/142065/creating-database-connections-do-it-once-or-for-each-query/398790#398790

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 1970-01-01
      • 1970-01-01
      • 2022-07-08
      • 2017-10-23
      • 1970-01-01
      相关资源
      最近更新 更多