ASP.NET-MySQL为每行大容量插入异步响应

本文关键字:插入 异步 响应 大容量 NET-MySQL ASP | 更新日期: 2023-09-27 18:24:59

我正在创建一个web应用程序,需要上传一个客户列表进入数据库,列表将来自CSV、TSV或EXCEL文件。

这些文件可能包含50-200条记录

我需要一种方法,为数据库中的每一行插入都向客户端返回响应。例如成功或失败。

我不希望执行所有INSERTS,然后返回结果摘要。

我只需要知道怎么做。如果你不能提供代码也没关系。但如果可以的话当然更好。

请随时标记、编辑或重新标记。。

谢谢。顺致敬意,

ASP.NET-MySQL为每行大容量插入异步响应

我将尝试一个基于会话、javascript定时器和AJAX调用的答案。

客户端和服务器之间最常见的通信方式是,客户端因此向服务器请求一些东西。这是在带有计时器的JavaScript中实现的,当时间过去时,进行AJAX调用并创建一个新的计时器,该计时器将执行相同的操作。

在服务器上,您可以启用AJAX方法,这些方法将成为AJAX调用的入口点。该方法将以插入的状态进行响应。

由于您在两个地方处理插入,一个在执行插入的页面中,另一个在AJAX方法中(它是静态的,您无法访问page实例),因此您需要在一个单独的类中移动逻辑,并在会话中跟踪插入。

因此代码将如下所示:

public class CsvInserts
{
   private IList<string> InsertsProgress {
        get {
             if (HttpContext.Current.Session["CsvInserts.Inserts"] == null )
                HttpContext.Current.Session["CsvInserts.Inserts"]  = new List<string>();
             return (IList<string>)HttpContext.Current.Session["CsvInserts.Inserts"];
        }
   }
   public IList<string> GetInsertsProgress() {
         return InsertsProgress;
   }
   public void InsertFile(string[] lines) {
         foreach ( var line in lines)
              {
                    var row = DataAccess.CsvInserts.Insert(line); // code to insert the line
                    InsertsProgress.Add(row.GetRelevantInfoForUser()); // successfully inserted or not and which line was inserted
              }
   }
}

在插入页面上,您将执行以下操作

protected void btInsert_OnClick(object sender, EventArgs e)
{
  var lines = .. get lines from the posted file;
  var insertManager = new CsvInserts();
  insertManager.InsertFile(lines);
}

WebMethod将是这样的

[WebMethod]
  public static IList<string> GetInsertsProgress()
  {
          var insertManager = new CsvInserts();
          return insertManager.GetInsertsProgress();
  }

在使用该定时器的客户端,您将一次又一次地调用此方法,直到插入完成。用jQuery或其他东西显示接收到的字符串。

这段C#代码来自内存,更像是一条指南。很抱歉没有提供JavaScipt代码。此外,当插入完成或创建新的大容量插入时,必须清除字符串列表。

这里有一些类似的东西,代码可以编译并工作,但需要一些"工作",我们必须进行单行更新,其中,我更喜欢使用线程池进行ASP.Net异步调用,因为我们遇到了任务和未处理的异常等问题,总是编码器出错。

// In the FileUpload Event Handler, or other Event Handler raised to start the process
ThreadPool.QueueUserWorkItem(new WaitCallback(DataLoader.InsertClientRecords), new Tuple<string, Guid>("PathToFile.csv", uniqueIdentifier));

// In the Ajax callback (or WebMethod as previously proposed) to update the UI, possible update a GridView with results etc.
List<Tuple<Guid, int, bool, string>> updates = DataLoader.GetProgressReports(uniqueIdentifier);

// Static class
public static class DataLoader
{
    private static readonly object locker = new object();
    // Tuple Guid for unique Identifier, int RowNumber, bool Result, string Message (if any)
    private static List<Tuple<Guid, int, bool, string>> results = new List<Tuple<Guid, int, bool, string>>();

    public static void InsertClientRecords(object stateInfo)
    {
        // string FilePath, Guid for unique Identifier
        Tuple<string, Guid> recordInfo = stateInfo as Tuple<string, Guid>;  
        if (recordInfo != null)
        {
            string filePath = recordInfo.item1;
            Guid id = recordInfo.item1;
            lock (locker)
            {
                // Update results List
            }            
        }
    }

    // Tuple Guid for unique Identifier, int RowNumber, bool Result, string Message (if any)
    public static List<Tuple<Guid, int, bool, string>> GetProgressReports(Guid identifier)
    {
        List<Tuple<Guid, int, bool, string>> updatedRecords = null; 
        bool lockTaken = false;
        try
        {
            // 1000 Millisecond Timeout so the Ajax callback does not hang.
            Monitor.TryEnter(locker, 1000, ref lockTaken);
            if (lockTaken)
            {
                updatedRecords = results.Where(r => (r.Item1 == identifier)).ToList();
                if (updatedRecords != null)
                    DataLoader.results.RemoveAll(r => (r.Item1 == identifier));
            }
        }
        finally
        {
            if (lockTaken)
                Monitor.Exit(locker);
        }  
        return updatedRecords;
    }