在后台Web Api中运行存储过程

本文关键字:运行 存储过程 Api 后台 Web | 更新日期: 2023-09-27 18:06:23

在我的Web Api应用程序中,我需要在这个主题中做一些事情:在ASP中运行后台任务的最佳方式。Net网络应用程序,也得到反馈?在应用程序中,用户可以上传一个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,如果它已经改变了。有什么建议吗?

在后台Web Api中运行存储过程

将async添加到方法中不会使方法调用异步。它只是表示正在处理当前请求的线程可以在等待一些网络/磁盘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);
}