简体   繁体   English

用于从同一存储过程更新数据或从中获取数据的程序逻辑

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

I am working on this project to create a Windows service that creates thread every 20 seconds. 我正在该项目上创建Windows服务,该服务每20秒创建一次线程。 This service get text and numbers from stored procedure and sends SMS to those number, and at every end of thread it returns result to stored procedure. 该服务从存储过程中获取文本和数字,并将SMS发送到这些数字,并且在线程的每一端,它将结果返回给存储过程。

In that logic, I have to call the stored procedure multiple times, so what I want to do is I want to get and update data at same time. 按照这种逻辑,我必须多次调用存储过程,所以我想做的是我想同时获取和更新数据。 The code flow is like this: this is the function that is called onStart of service. 代码流是这样的:这是称为服务的onStart的函数。

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

Code for GetInfo() : 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;        
}

Code for PushInfo() : 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();
    }
}

What I have thought so far is to pass _dt_sms_result to GetInfo() and delete PushInfo() as we'll be making only one call. 到目前为止,我一直想将_dt_sms_result传递给GetInfo()并删除PushInfo()因为我们将只进行一次调用。 And add 并添加

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

to GetInfo() . GetInfo()

But I am still confused with the logic where that GetInfo(with DT) should be placed on Prepare() method. 但是我仍然对应该将GetInfo(with DT)放在Prepare()方法上的逻辑感到困惑。

Can some one help me with the logic here? 有人可以帮我这里的逻辑吗? Thanks! 谢谢!

Basically what I did to solve that problem is that, I declared datatable( _dt_sms_result ) as a class property and it is static, now each thread will update to one datatable( _dt_sms_result ) locally, so when a new thread is created after 20 secs and calls GetInfo() it also sends _dt_sms_result to stored procedure as a paramter. 基本上,我为解决该问题所做的事情是,我将datatable( _dt_sms_result )声明为类属性,并且它是静态的,现在每个线程都将在本地更新为一个datatable( _dt_sms_result ),因此在20秒后创建新线程并调用GetInfo() ,它还会将_dt_sms_result作为参数发送到存储过程。 This call will get numbers, text and other info at same time and saves to datatable. 该调用将同时获取数字,文本和其他信息,并保存到数据表中。 To handle losing of data and deadlock during this call, I have locked this datatable until new datatable is retured by stored procedure. 为了处理此调用期间的数据丢失和死锁,我已锁定了此数据表,直到存储过程释放了新的数据表为止。

Changed code of GetInfo() : 更改了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;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM