在.net c中异步或并行地保存数据库中的记录

时间:2013-12-27 11:11:30

标签: c# .net asynchronous parallel-processing async-await

我有一项服务,我必须在从API获取后将大量记录保存到数据库。     同时我必须将这些记录从服务返回给调用者。     但问题是我在DB中保存记录需要很长时间,因此服务变慢。 我搜索了这个,发现了一些并行任务或异步& amp;等待。

我是这个概念的新手并且在使用中感到困惑

我调查了:

Running multiple C# Task Async http://msdn.microsoft.com/en-us/library/hh191443.aspx

但我不知道该怎么做。请帮助我:

下面是代码:

public List<SearchedItems> SearchItems(string ItemToSearch, string AuthenticationToken)
{
    var _list= getRecords from Api //100 records    

     //Task<int>.Factory.StartNew(() => _objBLLNutritionLog.FillNutritionTable(_tempList)); // also tried this

    saveToDb(_list); // need to run this asynchronously Or parallel (Taking long time)

    return _list;

}

我想将结果返回给调用者,另一方面想要填充db。 请建议。

谢谢

4 个答案:

答案 0 :(得分:9)

我希望您使用的是.NET 4.5。

让我们开始吧。首先使用SearchItems标记async函数:

public async List<SearchedItems> SearchItems(string ItemToSearch, string AuthenticationToken)
{
}

然后您可以await saveToDb任务:

var result = await Task.Factory.StartNew(()=> saveToDb(_list));

答案 1 :(得分:3)

异步或并行执行数据库命令不会加速错误的数据库代码,但 会损害性能。 100条记录是一个非常小的数字,这意味着数据库访问代码中发生了一些奇怪的事情。如果并行执行多个语句,则无法解决此问题。

首先,为了使操作并行执行,每个操作都需要一个单独的连接 - 这会导致更多的锁,更多的阻塞,更多的时间花在线上。

其次,通过线路建立连接和发送数据所花费的时间比执行实际INSERTUPDATE花费的时间多得多。即使您为每个记录执行一个语句,也不应该有任何性能问题。如果你这样做,可能是因为saveToDb做了一些奇怪的事情,或者你没有正确的索引,或者声明表现得非常糟糕。

最后,增加数据库插入的最佳方法是使用批量操作,如SQL Server的BULK INSERT一次插入大量记录,或SqlBulkCopy类。这些操作经过优化,可处理大量记录(数千个)。

在任何情况下,修复语句和数据库访问代码比并行运行语句要花费更多。

答案 2 :(得分:2)

除非操作真的是异步,否则我建议不要使用async-await。如果您的数据库客户端支持异步操作,那么继续,但使用Task.Factory.StartNewTask.Run只是将工作卸载到另一个线程。

然而,您可以并行运行这些任务,但只有当您的数据库并行工作时才会更快。如果让我们说它是一个SQL数据库并且您将数据插入到同一个表中,那么可能会锁定表并使您的任务运行得更慢。

但是,如果你想要的只是不阻塞调用者并在结果完全插入数据库之前返回结果,你可以这样做:

public List<SearchedItems> SearchItems(string ItemToSearch, string AuthenticationToken)
{
    var list = getRecords from Api
    Task.Run(() => SaveToDB(list));
    return list;
}

答案 3 :(得分:-2)

使用以下内容:

FX db1 = new FX();
LibraryManagementSystemEntities db2 = new LibraryManagementSystemEntities();

Thread thread1 = new Thread(delegate()
{
    db1.insert2(TextBox1.Text,TextBox2.Text);
    db2.insert1(TextBox1.Text,TextBox2.Text);
});
thread1.Start();