关于c#:AnyAsync()错误

Error on AnyAsync()

在我的ASP.NET Web API应用程序中,我在以下一行中的一项操作中遇到以下错误:

1
2
var dateExists = await _unitOfWork.GetRepository<Booking>().All()
    .AnyAsync(b => b.User.UserName == booking.User.UserName && b.Date == model.Date);

这是错误:

A second operation started on this context before a previous
asynchronous operation completed. Use 'await' to ensure that any
asynchronous operations have completed before calling another method
on this context. Any instance members are not guaranteed to be thread
safe.

但是,如您所见,我正在使用await。 我还在操作中的所有其他异步操作上使用了await。 那可能是什么问题呢?

编辑:

这是我的整个动作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[HttpPut]
[Route("Update")]
public async Task<IHttpActionResult> Put(BookingEditBindingModel model)
{
    if (!ModelState.IsValid)
    {
        // Return a bad request response if the model state is invalid...
        return BadRequest(ModelState);
    }

    try
    {
        var booking = await _unitOfWork.GetRepository<Booking>().FindAsync(model.BookingId);
        if (booking == null)
        {
            return NotFound();
        }

        // Only Admin is allowed to update other users' data...
        if (!User.IsInRole("Admin") && booking.User.UserName != User.Identity.Name)
        {
            return Unauthorized();
        }

        // There can only be one entry per date/user.
        if (model.Date != booking.Date)
        {
            var dateExists = await _unitOfWork.GetRepository<Booking>().All()
                .AnyAsync(b => b.User.UserName == booking.User.UserName && b.Date == model.Date);
            if (dateExists)
            {
                ModelState.AddModelError("Date","Data already exists for this date.");
                return BadRequest(ModelState);
            }
        }

        booking.Date = model.Date;
        // Change other properties...

        await _unitOfWork.SaveAsync();

        return Ok();
    }
    catch (Exception ex)
    {
        return InternalServerError(ex);
    }
}

更新:

我禁用了延迟加载,但是仍然有问题。 就像其他人猜到的一样,问题出在booking.User上,因为第一个查询中的FindAsync()不包含User。 我用下面的查询替换了第一个查询,问题已解决。

1
2
3
var booking = await _unitOfWork.GetRepository<Booking>().All()
    .Include(b => b.User)
    .SingleOrDefaultAsync(b => b.BookingId == model.BookingId);


我要走出去,猜测您已启用了延迟加载。 这将导致像booking.User.UserName这样的调用进入数据库以检索该值,并将其放入像AnyAsync这样的调用中可能会导致DbContext尝试打开第二个连接以在该值已打开之后检索该值。 一个用于AnyAsync语句。

在这种情况下,快速解决方案是在调用AnyAsync之前检索用户名。

1
2
3
var bookingUserName = booking.User.UserName;
var dateExists = await _unitOfWork.GetRepository<Booking>().All()
                .AnyAsync(b => b.User.UserName == bookingUserName && b.Date == model.Date);

更好的解决方法是在获取booking实例的呼叫中提前检索此信息,这样就不必进行其他往返操作。

就我个人而言,我总是禁用DbContext类型上的延迟加载,并使用Include语句来明确指定我希望通过任何调用检索的内容。 这使我可以更好地控制执行。