entity frameworkSaveChanges()与SaveChangesAsync()和Find()与FindAsync()

我一直在寻找2对以上的差异,但没有find任何文章解释清楚,以及何时使用这个或那个。

那么SaveChanges()SaveChangesAsync()什么区别呢?
Find()FindAsync()

在服务器端,当我们使用Async方法时,我们也需要添加await 。 因此,我不认为它是服务器端的asynchronous。

这是否有助于防止客户端浏览器上的UI阻塞? 或者他们之间有什么优点和缺点?

无论何时您需要在远程服务器上执行操作,程序都会生成请求,发送请求,然后等待响应。 我将使用SaveChanges()SaveChangesAsync()作为示例,但Find()FindAsync()同样适用。

假设你有一个需要添加到你的数据库的100+项目的myList列表。 为了插入,你的函数看起来像这样:

 using(var context = new MyEDM()) { context.MyTable.AddRange(myList); context.SaveChanges(); } 

首先创buildMyEDM实例,将MyEDM列表myListMyTableMyTable ,然后调用SaveChanges()以将更改保存到数据库中。 它的工作方式是你想要的,logging被提交,但是你的程序不能做任何事情,直到提交完成。 这可能需要很长时间,具体取决于您所做的事情。 如果您正在对logging进行更改,那么实体必须一次提交这些更改(我曾经保存2分钟才能更新)!

要解决这个问题,你可以做两件事情之一。 首先是你可以启动一个新的线程来处理插入。 虽然这将释放调用线程继续执行,但是您创build了一个正在坐在那里等待的新线程。 没有必要开销,这就是async await模式解决的问题。

对于I / O操作, await很快成为你最好的朋友。 从上面的代码部分,我们可以修改它是:

 using(var context = new MyEDM()) { Console.WriteLine("Save Starting"); context.MyTable.AddRange(myList); await context.SaveChangesAsync(); Console.WriteLine("Save Complete"); } 

这是一个非常小的变化,但是对代码的效率和性能有深远的影响。 那么会发生什么? 代码的MyEDM是相同的,你创build一个MyEDM的实例, MyEDM添加到MyTable 。 但是当你调用await context.SaveChangesAsync() ,代码的执行返回到调用函数! 所以当你在等待所有这些logging提交时,你的代码可以继续执行。 说包含上面代码的函数具有public async Task SaveRecords(List<MyTable> saveList)的签名,调用函数可以是这样的:

 public async Task MyCallingFunction() { Console.WriteLine("Function Starting"); Task saveTask = SaveRecords(GenerateNewRecords()); for(int i = 0; i < 1000; i++){ Console.WriteLine("Continuing to execute!"); } await saveTask; Console.Log("Function Complete"); } 

为什么你会有这样的function,我不知道,但它输出显示如何async await工作。 首先让我们看看发生了什么。

执行进入MyCallingFunctionFunction Starting然后Save Starting被写入到控制台,然后函数SaveChangesAsync()被调用。 此时,执行返回到MyCallingFunction并进入for循环写入“继续执行”达1000次。 当SaveChangesAsync()结束时,执行返回到SaveRecords函数,将Save Complete写入控制台。 一旦SaveRecords所有SaveRecords完成, SaveRecords执行就会在SaveChangesAsync()完成时继续执行。 困惑? 这是一个输出示例:

function启动
保存开始
继续执行!
继续执行!
继续执行!
继续执行!
继续执行!
 ....
继续执行!
保存完成!
继续执行!
继续执行!
继续执行!
 ....
继续执行!
function完成!

或者可能:

function启动
保存开始
继续执行!
继续执行!
保存完成!
继续执行!
继续执行!
继续执行!
 ....
继续执行!
function完成!

这是async await之美的美妙之处,你的代码可以继续运行,而你正在等待一些完成。 在现实中,你将会有一个更像这样的函数作为你的调用函数:

 public async Task MyCallingFunction() { List<Task> myTasks = new List<Task>(); myTasks.Add(SaveRecords(GenerateNewRecords())); myTasks.Add(SaveRecords2(GenerateNewRecords2())); myTasks.Add(SaveRecords3(GenerateNewRecords3())); myTasks.Add(SaveRecords4(GenerateNewRecords4())); await Task.WhenAll(myTasks.ToArray()); } 

在这里,你有四个不同的保存loggingfunction在同一时间 。 如果单独SaveRecords函数,则SaveRecords将使用async await更快地完成。

我还没有涉及的一件事就是await关键字。 这样做是停止执行当前函数,直到您正在等待的任何Task完成。 因此,在原来的SaveRecords的情况下,直到SaveRecords函数完成后, Function Complete行将不写入控制台。

长话短说,如果你有一个select使用async await ,你应该,因为它会大大提高你的应用程序的性能。

这个陈述是不正确的:

在服务器端,当我们使用asynchronous方法时,我们也需要添加await。

你不需要添加“等待”。 “await”只是C#中的一个方便的关键字,它使您能够在调用之后编写更多的代码行,而其他行将在Save操作完成后才会执行。 但正如您所指出的那样,只需调用SaveChanges而不是SaveChangesAsync即可完成该操作。

但从根本上说,asynchronous调用远不止于此。 这里的想法是,如果在保存操作正在进行时您可以执行其他工作(在服务器上),那么您应该使用SaveChangesAsync。 不要使用“等待”。 只要调用SaveChangesAsync,然后继续并行执行其他的东西。 这可能包括在Web应用程序中,甚至在“保存”完成之前向客户端返回响应。 但是,当然,您仍然需要检查Save的最终结果,以防万一失败,您可以将其传达给您的用户,或以某种方式logging下来。