Asp.net 如何使用WebService和jQueryAjax获得长时间运行的流程完成状态?

Asp.net 如何使用WebService和jQueryAjax获得长时间运行的流程完成状态?,asp.net,web-services,jquery,Asp.net,Web Services,Jquery,我创建了web服务,将大量数据上传到服务器(sql数据库) 我创建了两种方法,一种是 在服务器和其他服务器上上载数据是为了从保存的记录中获取状态,它将继续监视UploadingData方法,并每秒向客户端显示状态 以下是代码片段: AJAX //------------------------------ // Save uploaded file data in database //------------------------------

我创建了web服务,将大量数据上传到服务器(sql数据库)

我创建了两种方法,一种是 在服务器和其他服务器上上载数据是为了从保存的记录中获取状态,它将继续监视UploadingData方法,并每秒向客户端显示状态

以下是代码片段:

AJAX

//------------------------------
        // Save uploaded file data in database
        //------------------------------
        function SaveFileData() {
            DisplayMessage("Uploading bulk data from file to database, this will take time please wait...", "Loading", false);

            //This will try to diaplay status of saved records in database
            displayRecordStatusOn();

            $.ajax({
                type: "POST",
                url: "SaveData.asmx/SaveFileData",
                data: "{'FileName':'" + savedFileName + "', 'ClientID':'" + GetSelectedClient() + "','FileAutoID':'" + savedFileAutoID + "'}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (response) {
                    var result = jQuery.parseJSON(response.d);
                    if (result.Success == "False") {
                        DisplayMessage("Error : " + result.Message, "Failed", false);
                        return;
                    }
                    else {
                        //DisplayMessage("Datatransfer process 100% completed", "Success", false);
                        displayRecordStatusOff();
                        DisplayMessage(result.Message, "Success", false);
                        alert("100% Done!!");
                    }
                }
            });
        }

//This method called every second and get result from SaveFileData (web service method)
function displayRecordStatusOn() {
            $.ajax({
                type: "POST",
                url: "SaveData.asmx/GetRecordsInsertStatus",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (response) {
                    var result = jQuery.parseJSON(response.d);
                    if (result.Success == "False") {
                        console.log("F: " + result.Message);
                    }
                    else {
                        console.log("S: " + result.Message);
                    }
                }
            });
            recordStatusTimer = setTimeout("displayRecordStatusOn()", 1000);
        }
网络服务

 string RecordStatus = "";
     [WebMethod]
            [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
            public string SaveFileData(string FileName, string ClientID, string FileAutoID)
            {
//--HttpContext.Current.Session["CurrentCount"] = 0;
            HttpContext.Current.Cache.Remove("Counter" + FileAutoID);
                try
                {
                    DataTable dtExcelData = ExcelDataLoader(FileName, ClientID, "");
                    long TotalRecords = dtExcelData.Rows.Count;
                    long CopiedRecords = 0;
                    using (SqlConnection cn = new SqlConnection(GetConnectionString()))
                    {
                        SqlCommand cmdCopiedRecords = new SqlCommand("SELECT COUNT(*) FROM " + string.Format(DataBankTableFormat, FileAutoID) + ";", cn);
 //--HttpContext.Current.Session["TotalCount"] = TotalRecords;
                    HttpContext.Current.Cache.Insert("Counter" + FileAutoID, TotalRecords, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null);
                        cn.Open();
                        using (SqlBulkCopy copy = new SqlBulkCopy(cn))
                        {
                            copy.BatchSize = BatchSize;
copy.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);
                        copy.NotifyAfter = BatchSize;
                            for (int colIndex = 0; colIndex < dtExcelData.Columns.Count; colIndex++)
                            {
                                copy.ColumnMappings.Add(colIndex, colIndex);
                            }
                            copy.DestinationTableName = string.Format(DataBankTableFormat, FileAutoID);
                            copy.WriteToServer(dtExcelData);
                            CopiedRecords = System.Convert.ToInt32(cmdCopiedRecords.ExecuteScalar());
                            RecordStatus = string.Format("{0} of {1} copied successfully!", CopiedRecords, TotalRecords);
                        }
                        cn.Close();
                    }
                    Response = GetResponse(true, RecordStatus);
                }
                catch (Exception ex)
                {
                    Response = GetResponse(false, ex.Message);
                }
                return Response;
            }
           [WebMethod(EnableSession = true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public string GetRecordsInsertStatus(string FileAutoID)
        {
            try
            {
                Response = GetResponse(true, RecordStatus(FileAutoID));
            }
            catch (Exception ex)
            {
                Response = GetResponse(false, ex.Message);
            }
            return Response;
        }
    public string RecordStatus(string FileAutoID)
            {
                string response = "";
                //--response = string.Format("{0} of {1} copied successfully! at {2}", HttpContext.Current.Session["CurrentCount"], HttpContext.Current.Session["TotalCount"], DateTime.Now.ToString());
                response = string.Format("{0} of {1} copied successfully! at {2}", HttpContext.Current.Cache["Counter" + FileAutoID] == null ? "0" : HttpContext.Current.Cache["Counter" + FileAutoID].ToString(), 786, DateTime.Now.ToString());
                //return HttpContext.Current.Cache["Counter"+ClientID] == null ? "0" : HttpContext.Current.Cache["Counter"+ClientID].ToString();
                return response;
            }
            private static void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
            {
                HttpContext.Current.Session["CurrentCount"] = e.RowsCopied;
            }
string RecordStatus=“”;
[网络方法]
[ScriptMethod(ResponseFormat=ResponseFormat.Json)]
公共字符串SaveFileData(字符串文件名、字符串ClientID、字符串FileAutoID)
{
//--HttpContext.Current.Session[“CurrentCount”]=0;
HttpContext.Current.Cache.Remove(“计数器”+FileAutoID);
尝试
{
DataTable dtExcelData=ExcelDataLoader(文件名,ClientID,“”);
long TotalRecords=dtExcelData.Rows.Count;
长拷贝记录=0;
使用(SqlConnection cn=newsqlconnection(GetConnectionString()))
{
SqlCommand cmdCopiedRecords=新的SqlCommand(“从“+string.Format(DataBankTableFormat,FileAutoID)+”;”,cn中选择计数(*);
//--HttpContext.Current.Session[“TotalCount”]=TotalRecords;
HttpContext.Current.Cache.Insert(“Counter”+FileAutoID,TotalRecords,null,System.Web.Caching.Cache.NoAbsoluteExpiration,System.Web.Caching.Cache.NoSlidingExpiration,System.Web.Caching.CacheItemPriority.High,null);
cn.Open();
使用(SqlBulkCopy复制=新的SqlBulkCopy(cn))
{
copy.BatchSize=BatchSize;
copy.SqlRowsCopied+=新的SqlRowsCopiedEventHandler(OnSqlRowsCopied);
copy.NotifyAfter=批量大小;
对于(int colIndex=0;colIndex
问题:

public string RecordStatus
{
    get { return string.Format("{0} of {1} copied successfully!", Session["CurrentCount"], Session["TotalCount"]); }
}
private static void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
{
    Session["CurrentCount"] = (int)Session["CurrentCount"] + e.RowsCopied;
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string SaveFileData(string FileName, string ClientID, string FileAutoID)
{
    try
    {
        DataTable dtExcelData = ExcelDataLoader(FileName, ClientID, "");
        long TotalRecords = dtExcelData.Rows.Count;
        long CopiedRecords = 0;
        using (SqlConnection cn = new SqlConnection(GetConnectionString()))
        {
            // NO LONGER NEEDED HERE - SqlCommand cmdCopiedRecords = new SqlCommand("SELECT COUNT(*) FROM " + string.Format(DataBankTableFormat, FileAutoID) + ";", cn);

            cn.Open();

            // ADDED - get an initial count
            Session["CurrentCount"] = GetCount(cn);

            // ADDED - store total
            Session["TotalCount"] = TotalRecords;

            using (SqlBulkCopy copy = new SqlBulkCopy(cn))
            {
                copy.BatchSize = BatchSize;

                // ADDED - Set up the event handler to notify after 50 rows.
                copy.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);
                copy.NotifyAfter = BatchSize;

                for (int colIndex = 0; colIndex < dtExcelData.Columns.Count; colIndex++)
                {
                    copy.ColumnMappings.Add(colIndex, colIndex);
                }
                copy.DestinationTableName = string.Format(DataBankTableFormat, FileAutoID);
                copy.WriteToServer(dtExcelData);
            }
            cn.Close();
        }
        Response = GetResponse(true, RecordStatus);
    }
    catch (Exception ex)
    {
        Response = GetResponse(false, ex.Message);
    }
    return Response;
}
代码运行正常,只是在使用此方法(SaveFileData)后的SaveFileData处理过程中,我没有获得RecordStatus变量的值。

  • 我有全局变量RecordStatus,我正在更新它的值 SaveFileData方法,我正在尝试从中获取值 要在客户端浏览器上显示的GetRecordsInsertStatus方法。(但是这个 是否始终返回空白)

我不认为您可以按当前的方式初始化RecordStatus变量,因为每次调用web服务上的方法时都会重新实例化它(这就是为什么您总是得到“空白”)

您需要在SaveFileData方法中将状态保存/更新到数据库中的某种temp status表,并不断读取此行,以在GetRecordsInsertStatus方法上返回此信息

编辑

我刚刚意识到,您还可以将此信息放入应用程序缓存,在SaveFileData方法中插入并更新它,并在GetRecordsInsertStatus方法中从缓存中读取它。当应用程序缓存正好是静态类时,不需要使用带有哈希表的静态类

编辑2:我决定实施一个小样本项目,演示我在初始答案中的意思。我认为这很容易理解

下面是我的主页,脚本和标记混合在一起:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" language="javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>

    <script language="javascript" type="text/javascript">
        var pool = true;
        function displayRecordStatusOn() {
            $.ajax({
                type: "POST",
                url: "SaveData.asmx/GetRecordsInsertStatus",
                contentType: "application/json; charset=utf-8",
                data: '{"ClientID":"' + $('#CustomerIDs').val() + '"}',
                dataType: "json",
                success: function (response) {
                    if(pool)
                        $('#status').html('Current status: '+response.d);
                }
            });
            if(pool)
                setTimeout(displayRecordStatusOn, 1000);
        }

        function SaveFileData() {
            //This will try to diaplay status of saved records in database
            pool = true;
            $.ajax({
                type: "POST",
                url: "SaveData.asmx/SaveFileData",
                data: '{ "FileName": "whatever.txt" , "ClientID": "'+$('#CustomerIDs').val()+'" ,"FileAutoID":"1"}',
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (response) {
                    if (response.d == 'Done saving file') {
                        pool = false;
                        $('#status').html(response.d);
                    }
                }
            });
            displayRecordStatusOn();
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
         <input type="button" onclick="SaveFileData();" value="Start Upload Process" />
         <select id="CustomerIDs" >
         <option value="1">Customer 1</option>
         <option value="2">Customer 2</option>
         <option value="3">Customer 3</option>
         <option value="4">Customer 4</option>
         </select>
         <div id="status"></div>
    </div>
    </form>
</body>
</html>
最后,这是所有内容的外观(显示两个同时上载文件的用户):


我认为正确的做法是使用
SqlBulkCopy.NotifyAfter
属性。根据:

该物业的设计目的是
private static void OnSqlRowsCopied(object sender, SqlRowsCopiedEventArgs e)
{
    Session["CurrentCount"] = (int)Session["CurrentCount"] + e.RowsCopied;
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string SaveFileData(string FileName, string ClientID, string FileAutoID)
{
    try
    {
        DataTable dtExcelData = ExcelDataLoader(FileName, ClientID, "");
        long TotalRecords = dtExcelData.Rows.Count;
        long CopiedRecords = 0;
        using (SqlConnection cn = new SqlConnection(GetConnectionString()))
        {
            // NO LONGER NEEDED HERE - SqlCommand cmdCopiedRecords = new SqlCommand("SELECT COUNT(*) FROM " + string.Format(DataBankTableFormat, FileAutoID) + ";", cn);

            cn.Open();

            // ADDED - get an initial count
            Session["CurrentCount"] = GetCount(cn);

            // ADDED - store total
            Session["TotalCount"] = TotalRecords;

            using (SqlBulkCopy copy = new SqlBulkCopy(cn))
            {
                copy.BatchSize = BatchSize;

                // ADDED - Set up the event handler to notify after 50 rows.
                copy.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);
                copy.NotifyAfter = BatchSize;

                for (int colIndex = 0; colIndex < dtExcelData.Columns.Count; colIndex++)
                {
                    copy.ColumnMappings.Add(colIndex, colIndex);
                }
                copy.DestinationTableName = string.Format(DataBankTableFormat, FileAutoID);
                copy.WriteToServer(dtExcelData);
            }
            cn.Close();
        }
        Response = GetResponse(true, RecordStatus);
    }
    catch (Exception ex)
    {
        Response = GetResponse(false, ex.Message);
    }
    return Response;
}