更新和获取数据的程序逻辑 to/from 相同的存储过程

Program logic to Update and Get data to/from same stored procedure

我正在这个项目上创建一个每 20 秒创建一个线程的 Windows 服务。该服务从存储过程中获取文本和数字并将 SMS 发送到这些号码,并且在线程的每一端它 returns 结果到存储过程。

按照这个逻辑,我必须多次调用存储过程,所以我想做的是同时获取和更新数据。代码流程是这样的:这是调用onStart of service的函数。

public void Prepare(object state)
{
    DataTable _dt = new DataTable();
    DataTable _dt_sms_result = new DataTable();

    _dt = GetInfo();

    if (_dt != null)
    {
        _dt_sms_result.Columns.Add("sms_id", typeof(int));
        _dt_sms_result.Columns.Add("send_time", typeof(DateTime));
        _dt_sms_result.Columns.Add("result", typeof(string));

        foreach (DataRow dr in _dt.Rows)
        {
            bool status = sendMsg(dr["smsid"].ToString(), dr["number"].ToString(), dr["messagetxt"].ToString(), dr["from"].ToString(), dr["to"].ToString());
            Thread.Sleep(1000);
            DataRow lvlrow = _dt_sms_result.NewRow();
            lvlrow["sms_id"] = dr["sms_id"];
            lvlrow["send_time"] = DateTime.Now;

            if (status)
                lvlrow["result"] = "Message Sent";
            else
                lvlrow["result"] = "Sending Failed";

            _dt_sms_result.Rows.Add(lvlrow);
        }//end foreach
        PushInfo(_dt_sms_result);
    }

GetInfo() 的代码:

public DataTable GetInfo()
{
    cmd.CommandText = "StoreProc_511";
    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Clear();

    cmd.Parameters.AddWithValue("@username", "******");            
    cmd.Parameters.AddWithValue("@authcode", "******");

    DataTable dt = new DataTable();

    try
    {
        Connect();
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        da.Fill(dt);              
    }
    catch (SqlException se)
    {
        MyLog.Write(new LogPacket(se, DateTime.Now));
        return null;
    }
    finally
    {
        Disconnect();
    }
    return dt;        
}

PushInfo() 的代码:

public void PushInfo(DataTable dt_sms_result)
{
    int res = -1;
    cmd.CommandText = "StoreProc_511";
    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Clear();
    cmd.Parameters.AddWithValue("@username", "*****");            
    cmd.Parameters.AddWithValue("@authcode", "*****");

    SqlParameter tvpParam = cmd.Parameters.AddWithValue("@sms_result", dt_sms_result);
    tvpParam.SqlDbType = SqlDbType.Structured;

    try
    {
        Connect();
        res = cmd.ExecuteNonQuery();
    }
    catch (SqlException se)
    {
        MyLog.Write(new LogPacket(se, DateTime.Now));            
        Disconnect();           
    }
    finally
    {
        Disconnect();
    }
}

到目前为止,我的想法是将 _dt_sms_result 传递给 GetInfo() 并删除 PushInfo(),因为我们只会进行一次调用。并添加

SqlParameter tvpParam = cmd.Parameters.AddWithValue("@sms_result", dt_sms_result);
tvpParam.SqlDbType = SqlDbType.Structured;

GetInfo()

但我仍然对 GetInfo(with DT) 应该放在 Prepare() 方法上的逻辑感到困惑。

有人可以帮我解释这里的逻辑吗?谢谢!

基本上我解决这个问题的方法是,我将 datatable(_dt_sms_result) 声明为 class 属性 并且它是静态的,现在每个线程都会更新为一个datatable(_dt_sms_result) 在本地,因此当在 20 秒后创建新线程并调用 GetInfo() 时,它还会将 _dt_sms_result 作为参数发送到存储过程。此调用将同时获取号码、文本和其他信息并保存到数据表中。为了处理此调用期间的数据丢失和死锁,我已锁定此数据表,直到新数据表被存储过程恢复。

更改了 GetInfo() 的代码:

public DataTable GetInfo()
{
    DataTable dt = new DataTable();

    cmd.CommandText = "StoreProc_511";
    cmd.CommandType = CommandType.StoredProcedure;

    cmd.Parameters.Clear();
    cmd.Parameters.AddWithValue("@username", "*****");            
    cmd.Parameters.AddWithValue("@authcode", "*****");

    lock (_dt_sms_result) { 
        SqlParameter tvpParam = cmd.Parameters.AddWithValue("@dt_sms_res", _dt_sms_result);
        tvpParam.SqlDbType = SqlDbType.Structured;


        try
        {
            Connect();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(dt);
            _dt_sms_result.Rows.Clear();

        }
        catch (SqlException se)
        {
            MyLog.Write(new LogPacket(se, DateTime.Now));                
        }
        finally
        {
            Disconnect();
        }
    }
    return dt;

}