在ASP.NET中,为什么DbSet.LastAsync()不存在?

在ASP.NET中,为什么DbSet.LastAsync()不存在?,asp.net,asp.net-web-api,async-await,entity-framework-6,Asp.net,Asp.net Web Api,Async Await,Entity Framework 6,我已经编写了一些代码来实现一些web API。 此API方法返回Foo表的最后一条记录 public class FooController : ApiController { private FooContext db = new FooContext(); // GET: api/Foo [ResponseType(typeof(Foo))] public async Task<IHttpActionResult> GetLastFoo()

我已经编写了一些代码来实现一些web API。 此API方法返回Foo表的最后一条记录

public class FooController : ApiController
{
    private FooContext db = new FooContext();

    // GET: api/Foo
    [ResponseType(typeof(Foo))]
    public async Task<IHttpActionResult> GetLastFoo()
    {
        Foo foo = await db.Foo.Last();
        if (foo == null)
        {
            return NotFound();
        }
        return Ok(foo);
    }
}
公共类FooController:ApicController
{
private FooContext db=new FooContext();
//获取:api/Foo
[响应类型(类型(Foo))]
公共异步任务GetLastFoo()
{
Foo-Foo=wait db.Foo.Last();
if(foo==null)
{
返回NotFound();
}
返回Ok(foo);
}
}
我想使这个API异步,但没有LastAsync()方法。 为什么以及如何解决它? 提前谢谢。

关于如何解决这个问题

你可以用

 await Task.Run(()=>db.Foo.Last());

您不应在ASP.NET中使用Task.Run:

ASP.NET上的Async和await都是关于I/O的。它们确实擅长于 读取和写入文件、数据库记录和RESTAPI。然而, 它们不适合CPU限制的任务。你可以开始一些背景知识 通过等待任务来工作。运行,但这样做没有意义。事实上 这实际上会通过干扰 ASP.NET线程池启发式。如果您有CPU绑定的工作要做 在ASP.NET中,最好是直接在请求上执行它 线一般来说,不要将工作排队到上的线程池 ASP.NET

但这并不意味着不能在ASP.NET中使用async和Wait进行I/O(这正是您想要的),只需使用真正的异步方法,而不是在同步方法上使用虚假的异步包装器(这只会将工作推送到其他线程池线程中,您会这样做)。

由于EF中没有LastAsync方法,我建议您使用OrderBy按需要对集合进行排序,并使用method(或支持lambda谓词的FirstAsync重载)而不是Last方法,FirstAsync是EF中支持的真正的异步I/O方法。

有关何时适合使用Task.Run的更多信息,可以在Stephen Cleary的博客文章中找到


你的问题是为什么没有LastAsync方法,应该直接问设计EF api的Microsoft团队,但我猜他们没有费心实现它,因为使用FirstAsync方法很容易实现我建议的相同功能。

该代码的工作版本如下所示:

    public class FooController : ApiController
{
    private FooContext db = new FooContext();

    // GET: api/Foo
    [ResponseType(typeof(Foo))]
    public async Task<IHttpActionResult> GetLastFoo()
    {
        Foo foo = await db.Foo.OrderByDesc(x=> x.Timestamp).FirstOrDefaultAsync(); 
        if (foo == null)
        {
            return NotFound();
        }
        return Ok(foo);
    }
}
公共类FooController:ApicController
{
private FooContext db=new FooContext();
//获取:api/Foo
[响应类型(类型(Foo))]
公共异步任务GetLastFoo()
{
Foo Foo=await db.Foo.OrderByDesc(x=>x.Timestamp).FirstOrDefaultAsync();
if(foo==null)
{
返回NotFound();
}
返回Ok(foo);
}
}

Last etc不适用于EF IQueryable,因为SQL没有等效的命令

,但您不应该在ASP.NET中使用。它只会消耗资源,表现最差。你绝对不应该这样做。这会白白浪费资源。这没有好处。