ASP.NET - MySQL批量插入每行的异步响应

时间:2012-02-18 15:58:56

标签: c# asp.net mysql ajax

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

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

我需要一种方法来向客户端回复每次插入数据库的行。 如成功或失败。

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

我只需要知道如何做到这一点。如果您无法提供代码,那就没关系。但如果可以,当然会更好。

请随意标记或编辑或重新标记..

谢谢。最诚挚的问候!!!

2 个答案:

答案 0 :(得分:2)

我会尝试一个答案,并基于使用Session,javascript计时器和AJAX调用。

客户端和服务器之间最常见的通信方式就像客户端因此询问服务器的某些内容。这是在带有计时器的JavaScript中实现的,当时间过去后,进行AJAX调用并创建一个新的计时器,它将执行相同的操作。

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

由于您在两个地方处理插入,一个在页面中执行插入,另一个在AJAX方法中(这是静态的,您将无法访问Page实例),您需要单独移动逻辑class和跟踪Session中的插入。

所以代码看起来像这样:

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代码。此外,您必须在插入完成或创建新的批量插入时清除字符串列表。

答案 1 :(得分:0)

Heres类似的东西,代码组合和工作,但需要一点“工作”,我们做单行更新,我更喜欢使用ThreadPool进行ASP.Net异步调用,因为我们遇到了Task和Unhandled的问题异常等,总是编码错误。

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