C# ASP.NET-MySQL为每行批量插入异步响应
我正在创建一个web应用程序,我需要上传一个客户端列表 在数据库中,列表将来自CSV、TSV或EXCEL文件 这些文件可能包含50-200条记录 我需要一种方法为数据库中的每一行插入返回一个响应给客户端。 例如成功或失败 我不希望执行所有插入,然后返回结果摘要 我需要的只是如何做到这一点的想法。如果你不能提供代码,那没关系。但如果可以,当然更好 请随时标记、编辑或重新标记C# ASP.NET-MySQL为每行批量插入异步响应,c#,asp.net,mysql,ajax,C#,Asp.net,Mysql,Ajax,我正在创建一个web应用程序,我需要上传一个客户端列表 在数据库中,列表将来自CSV、TSV或EXCEL文件 这些文件可能包含50-200条记录 我需要一种方法为数据库中的每一行插入返回一个响应给客户端。 例如成功或失败 我不希望执行所有插入,然后返回结果摘要 我需要的只是如何做到这一点的想法。如果你不能提供代码,那没关系。但如果可以,当然更好 请随时标记、编辑或重新标记 多谢各位。最好的问候 我将尝试一个答案,它基于使用会话、javascript计时器和AJAX调用。 客户端和服务器之间最
多谢各位。最好的问候 我将尝试一个答案,它基于使用会话、javascript计时器和AJAX调用。
客户端和服务器之间最常见的通信方式类似于客户端向服务器请求某些东西。这是在JavaScript中通过计时器实现的,当时间流逝时,进行AJAX调用并创建一个新的计时器,该计时器将执行相同的操作。
在服务器上,您可以启用,这些将是AJAX调用的入口点。该方法将响应插入的状态。
由于您在两个位置处理插入,一个在执行插入的页面中,另一个在AJAX方法中(这是静态的,您将无法访问页面实例),因此需要在单独的类中移动逻辑,并在会话中跟踪插入。
因此代码如下所示:
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
}
}
}
WebMethod将是这样的
[WebMethod]
公共静态IList GetInsertsProgress()
{
var insertManager=new CsvInserts();
返回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;
}
//在FileUpload事件处理程序中,或为启动进程而引发的其他事件处理程序中
QueueUserWorkItem(新的WaitCallback(DataLoader.InsertClientRecords),新的元组(“PathToFile.csv”,uniqueIdentifier));
//在Ajax回调(或之前建议的WebMethod)中,更新UI,可能会使用结果更新GridView等。
列表更新=DataLoader.GetProgressReports(uniqueIdentifier);
//静态类
公共静态类数据加载器
{
私有静态只读对象锁定器=新对象();
//唯一标识符、整数行数、布尔结果、字符串消息(如果有)的元组Guid
私有静态列表结果=新列表();
公共静态void InsertClientRecords(对象状态信息)
{
//字符串文件路径,唯一标识符的Guid
Tuple recordInfo=stateInfo作为Tuple;
if(recordInfo!=null)
{
字符串filePath=recordInfo.item1;
Guid id=recordInfo.item1;
锁(储物柜)
{
//更新结果列表
}
}
}
//唯一标识符、整数行数、布尔结果、字符串消息(如果有)的元组Guid
公共静态列表GetProgressReports(Guid标识符)
{
列表updateRecords=null;
bool-locktake=false;
尝试
{
//1000毫秒超时,因此Ajax回调不会挂起。
监视器。TryEnter(储物柜,1000,参考锁定);
如果(已锁定)
{
updateRecords=results.Where(r=>(r.Item1==identifier)).ToList();
if(updateRecords!=null)
DataLoader.results.RemoveAll(r=>(r.Item1==identifier));
}
}
最后
{
如果(已锁定)
监控出口(储物柜);
}
返回更新的记录;
}
客户机是否需要与插件交互?比如插入中间的“取消”之类的东西?谢谢您的响应……嗯,如果我能添加这个特性就好了……但不是必须的。再次感谢+ 1它是一个有效且合理的问题。“谢谢劳埃德。我希望有人尽快回答。谢谢你的详细回应。基于这些逻辑,我正在尝试一些东西。谢谢。很多。我会在我成功后回来的=)
[WebMethod]
public static IList<string> GetInsertsProgress()
{
var insertManager = new CsvInserts();
return insertManager.GetInsertsProgress();
}
// 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;
}