使用实体创建基本的ASP.NET Core 2.1 MVC API Web应用程序时,可以在选择模型和dbContext之后自动生成控制器(RMB->添加->控制器...->具有动作的API控制器,使用实体框架)
我想知道为什么除了返回所有表的基本Get()方法之外,所有生成的方法都是异步的?这是错误吗?这是一个数据库调用,因此我希望它是异步的。在这种情况下使用异步调用没有真正的好处吗?如果是,为什么?
// GET: api/User
[HttpGet]
public IEnumerable<User> GetUsers()
{
return _context.Users;
}
答案 0 :(得分:2)
return _context.Users
仅返回类型DbSet<Users>
的对象。它不会对其进行迭代或进行任何工作,而只是传递一个允许您访问数据库数据的对象。
DbSet<T>
也是IQueryable<T>
,这意味着直到调用诸如.ToList()
或.Single(x=>x.Id == idToLookFor)
如果要异步迭代它,那么将有一个异步Get()方法,例如;
return await _context.Users.ToListAsync()
我意识到实际上没有回答您的问题,
您极不可能希望返回整个表。 (SELECT * FROM [Users])所以这里的Get()
方法是一种反模式(在我看来**),称为“公开IQueryable”
因此,您可以在控制器中执行类似的操作
_context.Get().Where(user=>user.FirstName == 'Steve').ToList()
或者您可以使它与数据库调用异步,
await _context.Get().Where(user=>user.FirstName == 'Steve').ToListAsync()
那么,生成的模板Get()
是否错误?不,但是我认为您不应该将IQueryable作为公共方法公开,因此我不同意。
IQueryable<T>
var query = _context.Users; //SQL: * FROM [Users]
query = query.Where(x=>x.Name == "Steve");
//SQL: * FROM [Users] WHERE Name = 'Steve'
query = query.Where(x=>x.wearsHats == true);
//SQL: * FROM [Users] WHERE Name = 'Steve' AND WearsHats = true
query = query.Select(x=>x.Name);
//SQL: Name FROM [Users] WHERE Name = 'Steve' AND WearsHats = true
var result = query.ToList()
//SQL: SELECT Name FROM [Users] WHERE Name = 'Steve' AND WearsHats = true
答案 1 :(得分:0)
是的,这与所有其他异步操作非常不一致。我认为没有任何具体原因。我认为Microsoft只是忘记更新模板的这一部分。我希望会生成以下内容:
// GET: api/User
[HttpGet]
public async Task<ActionResult<IEnumerable<User>>> GetUsers()
{
return await _context.Users.ToListAsync();
}
即使是一个线性操作也可以从异步中受益-IIS线程在数据库查询期间不会被阻止。您可以在SO的其他问题中了解更多有关此内容的信息,例如:When should I use Async Controllers in ASP.NET MVC?
编辑:您可以在github上找到模板源。您可以在第38-42行中看到,在最新版本中,此操作已更新,并且将以异步方式生成,与我上面所写的完全相同。