简体   繁体   English

尝试获取结果列表时出现等待/异步错误

[英]Await/Async error when trying to get a list of results

Can someone explain to me why I am getting a design/compile time error for this.有人可以向我解释为什么我会为此收到设计/编译时错误。

I am trying to get the last Guid for each table, based on alast update date or created date.我试图根据最后更新日期或创建日期获取每个表的最后一个 Guid。

var accountId = context.Account.OrderBy(x => x.LastUpdateDate).ThenBy(x=>x.LastUpdateDate).FirstOrDefaultAsync(x => x.UserAccount.ExternalId == _jwt.HomeAccountId).ExternalId;
var transactionLineId = context.TransactionLine.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.Transaction.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId).ExternalId;
var transactionId = context.Transaction.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId).ExternalId;
var budgetId = context.Budget.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.UserAccount.ExternalId == _jwt.HomeAccountId).ExternalId;
var scheduleId = context.Schedule.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId).ExternalId;

And then, await each repsonse and pass to a method.然后,等待每个响应并传递给一个方法。

var guids = new List<Guid> { await accountId, await transactionLineId, await transactionId, await budgetId, await scheduleId };

var checkGuid = MungeTwoGuids(guids);

But I get the error:但我收到错误:

CS1061 'Task' does not contain a definition for 'ExternalId' and no accessible extension method 'ExternalId' accepting a first argument of type 'Task' could be found (are you missing a using directive or an assembly reference?) CS1061“Task”不包含“ExternalId”的定义,并且找不到接受“Task”类型的第一个参数的可访问扩展方法“ExternalId”(您是否缺少 using 指令或程序集引用?)

This happens on the first line.这发生在第一行。 I thought I can call all those selects.... at once, basically... and then await all responses.我以为我可以调用所有这些选择......一次,基本上......然后等待所有响应。 Instead of call, wait, call, wait....而不是呼叫,等待,呼叫,等待......

Is this not the right way to achieve what I am trying to do?这不是实现我想要做的事情的正确方法吗? Well, it's not, as I have an error, but am I on the wrong track with my understanding of await?好吧,不是,因为我有错误,但是我对 await 的理解是否走错了路?

I then removed the field from the select, and try to get it like this, but ... Nope.然后我从选择中删除了该字段,并尝试像这样获得它,但是......不。

await accountId.Result.ExternalId,

Your FirstOrDefaultAsync returns a Task<T> , not T itself, and thus has no ExternalId .您的FirstOrDefaultAsync返回Task<T> ,而不是T本身,因此没有ExternalId

Normally you would have 2 options:通常你会有 2 个选择:

  • select the ExternalId upfront in a Select and await the task later, orSelect预先选择ExternalId并稍后等待任务,或者
  • await the Task<T> first, the result will be a T , conaining your property so you can access it.首先等待Task<T> ,结果将是T ,包含您的财产,以便您可以访问它。

But, as @GSerg notes: the first option does not apply because executing parralell queries will result in a concurrency exception .但是,正如@GSerg 所指出的:第一个选项不适用,因为执行 parralell 查询将导致并发异常


So, in your case it makes sense to await the FirstOrDefaultAsync directly, and use a Select , ??因此,在您的情况下,直接等待FirstOrDefaultAsync并使用Select?? or a null check to overcome the possible null ref exception.或空检查以克服可能的空引用异常。


Try to avoid the accountId.Result.ExternalId because it will make your code run synchronously and you'll loose the benefits of the asynchronous calls.尽量避免使用accountId.Result.ExternalId因为它会使您的代码同步运行,并且您将失去异步调用的好处。 See: What is the difference between await Task<T> and Task<T>.Result?请参阅: await Task<T> 和 Task<T>.Result 之间有什么区别?

You should change your code like this:您应该像这样更改代码:

 var accountId = context.Account.OrderBy(x => x.LastUpdateDate).ThenBy(x=>x.LastUpdateDate).FirstOrDefaultAsync(x => x.UserAccount.ExternalId == _jwt.HomeAccountId);
 var transactionLineId = context.TransactionLine.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.Transaction.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId);
 var transactionId = context.Transaction.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId);
 var budgetId = context.Budget.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.UserAccount.ExternalId == _jwt.HomeAccountId);
 var scheduleId = context.Schedule.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId);


var guids = new List<Guid> { 
          (await accountId).ExternalId,
          (await transactionLineId).ExternalId,
          (await transactionId).ExternalId,
          (await budgetId).Externalid,
          (await scheduleId).EternalId };

var checkGuid = MungeTwoGuids(guids);

In that way, you are first awaiting the Tasks you started and then use the 'ExternalId' property of the result each tasks returns.这样,您首先等待您启动的任务,然后使用每个任务返回的结果的“ExternalId”属性。

Important edit : The changes above will solve the original problem, but as was pointed out in the comment by GSerg below, you will get an exception, since EF does not allow simultaneous asynchroneous operations on the same context.重要编辑:上述更改将解决原始问题,但正如下面 GSerg 在评论中指出的那样,您将得到一个例外,因为 EF 不允许在同一上下文中同时进行异步操作。

You could solve this by:您可以通过以下方式解决此问题:

a) immediately await each task a) 立即等待每个任务

b) if you really want parallel execution: create a separate context for each task b) 如果你真的想要并行执行:为每个任务创建一个单独的上下文

Please do like below.请像下面那样做。

var accountId = (await context.Account.OrderBy(x => x.LastUpdateDate).ThenBy(x=>x.LastUpdateDate).FirstOrDefaultAsync(x => x.UserAccount.ExternalId == _jwt.HomeAccountId)).ExternalId;
var transactionLineId = (await context.TransactionLine.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.Transaction.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId)).ExternalId;
var transactionId = (await context.Transaction.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId)).ExternalId;
var budgetId = (await context.Budget.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.UserAccount.ExternalId == _jwt.HomeAccountId)).ExternalId;
var scheduleId = (await context.Schedule.OrderBy(x => x.LastUpdateDate).ThenBy(x => x.LastUpdateDate).FirstOrDefaultAsync(x => x.CreditAccount.UserAccount.ExternalId == _jwt.HomeAccountId)).ExternalId

Then然后

var guids = new List<Guid> {accountId, transactionLineId, transactionId, budgetId, scheduleId};
var checkGuid = MungeTwoGuids(guids);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM