【问题标题】:Run stored procedure in a background Web Api在后台 Web Api 中运行存储过程
【发布时间】:2015-08-05 10:21:19
【问题描述】:

在我的 Web Api 应用程序中,我需要在这个主题中执行类似的操作:Best way to run a background task in ASP.Net web app and also get feedback? 在应用程序中,用户可以上传一个 excel 文件,然后将其数据导入数据库中的表。一切正常,但导入过程可能需要很长时间(大约 20 分钟,如果 excel 有很多行),并且当进程启动时,页面被阻止,用户必须一直等待。我需要在后台运行这个导入过程。

我有一个使用这种 POST 方法的控制器:

[HttpPost]
public async Task<IHttpActionResult> ImportFile(int procId, int fileId)
{
    string importErrorMessage = String.Empty;

    // Get excel file and read it
    string path = FilePath(fileId);
    DataTable table = GetTable(path);

    // Add record for start process in table Logs
    using (var transaction = db.Database.BeginTransaction()))
    {
        try
        {
            db.uspAddLog(fileId, "Process Started", "The process is started");
            transaction.Commit();
        }
        catch (Exception e)
        {
            transaction.Rollback();
            importErrorMessage = e.Message;
            return BadRequest(importErrorMessage);
        }
    }

    //Using myHelper start a store procedure, which import data from excel file
    //The procedure also add record in table Logs when it is finished
    using (myHelper helper = new myHelper())
    helper.StartImport(procId, fileId, table, ref importErrorMessage);

        if (!String.IsNullOrEmpty(importErrorMessage))
        return BadRequest(importErrorMessage);

    return Ok(true);
}

我还有一个 GET 方法,它返回有关文件及其进程的信息

[HttpGet]
[ResponseType(typeof(FileDTO))]
public IQueryable<FileDTO> GetFiles(int procId)
{
    return db.LeadProcessControl.Where(a => a.ProcessID == procId)
                                .Project().To<FileDTO>();
}

它像这样返回 JSON:

{
  FileName = name.xlsx
  FileID = 23
  ProcessID = 11
  Status = Started
}

此方法适用于 GRID

File name | Status | Button to run import | Button to delete file

这个Status 来自表Logs 并在FileDTO 中放置了最后一个值,例如,如果我上传文件status 将是“文件上传”当我运行导入status 将是“已开始”,当它完成时status 将是“完成”。但是现在页面在导入过程运行时被锁定,所以状态总是“完成”。

所以我需要在后台运行程序,并且 GET 方法应该返回新的Status 如果它已被更改。有什么建议吗?

【问题讨论】:

  • 这是在 IIS 之类的东西上运行的吗? Web 服务器上任何长时间运行的任务的问题在于,它可能会根据内存使用情况决定部分回收。如果您谈论 20 分钟,我会将其发送到其他(非 Web)应用程序进程,可能通过队列或服务总线。然后,该任务可以在 Web 应用可以检索的某个地方记录其进度,或者更好地发回有关进度的消息。
  • @Mant101 ,是的,它正在 IIS 中运行
  • 检查它的回收设置,如果你在达到内存限制或上传运行时可能发生的其他设置时回收它是易受攻击的。如果您确定它在上传期间永远不会回收,您可以启动一项任务来完成这项工作,并在您可以在 GetFiles(数据库、应用程序变量、静态属性等)中检索的某个位置将其设置为状态。尽量保持任务中的所有文件/数据库访问异步,以尽量减少影响。

标签: c# sql .net asp.net-web-api


【解决方案1】:

向方法添加异步不会使您的方法调用异步。它只是表明正在处理当前请求的线程可以在等待某些网络/磁盘 IO 时被重用于处理其他请求。当客户端调用此方法时,它只会在方法完成后得到响应。换句话说,异步完全是服务器端的事情,与客户端调用无关。您需要在单独的线程中启动长时间运行的进程,如下所示。但最佳做法是不要将 Web 应用程序用于如此长时间运行的处理,而是在单独的 Windows 服务中进行长时间处理。

[HttpPost]
    public async Task<IHttpActionResult> ImportFile(int procId, int fileId)
{
string importErrorMessage = String.Empty;

// Get excel file and read it
string path = FilePath(fileId);
DataTable table = GetTable(path);

// Add record for start process in table Logs
using (var transaction = db.Database.BeginTransaction()))
{
    try
    {
        db.uspAddLog(fileId, "Process Started", "The process is started");
        transaction.Commit();
    }
    catch (Exception e)
    {
        transaction.Rollback();
        importErrorMessage = e.Message;
        return BadRequest(importErrorMessage);
    }
}

         //Start long running process in new thread
         Task.Factory.StartNew(()=>{

         using (myHelper helper = new myHelper())
        {
           helper.StartImport(procId, fileId, table, ref importErrorMessage);

          //** As this code is running background thread you cannot return anything here. You just need to store status in database. 

         //if (!String.IsNullOrEmpty(importErrorMessage))
         //return BadRequest(importErrorMessage);
       }

        });

//You always return ok to indicate background process started
return Ok(true);
}

【讨论】:

  • 我发现最好不要将网络应用程序用于长流程,但出于某些原因我需要它)谢谢您的帮助,我会使用它。您可以建议我如何检查Status 并从Logs 返回最后一个值?
  • 您可以使用应用程序变量来存储状态和上次日志,然后创建一个新的 Web api 方法来返回状态。您的 api 的客户端将需要定期汇集此状态方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 2012-10-13
  • 2010-12-24
  • 2021-09-16
  • 2014-08-15
  • 1970-01-01
  • 2012-06-03
相关资源
最近更新 更多