- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在使用 Asp.Net Core Identity 并尝试简化一些将用户列表及其角色转换到 ViewModel 的代码。这段代码有效,但在试图简化它的过程中,我陷入了错误和好奇的疯狂漩涡中。
这是我的工作代码:
var allUsers = _userManager.Users.OrderBy(x => x.FirstName);
var usersViewModel = new List<UsersViewModel>();
foreach (var user in allUsers)
{
var tempVm = new UsersViewModel()
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
DisplayName = user.DisplayName,
Email = user.Email,
Enabled = user.Enabled,
Roles = String.Join(", ", await _userManager.GetRolesAsync(user))
};
usersViewModel.Add(tempVm);
}
为了简化代码,我想我可以做这样的事情(损坏的代码):
var usersViewModel = allUsers.Select(user => new UsersViewModel
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
DisplayName = user.DisplayName,
Email = user.Email,
Enabled = user.Enabled,
Roles = string.Join(", ", await _userManager.GetRolesAsync(user))
}).ToList();
这会中断,因为我没有在 user 之前的 lambda 表达式中使用 async 关键字。但是,当我在 user 之前添加异步时,我又收到另一个错误,提示 “Async lambda expressions cannot be converted to expression trees”
我的猜测是 GetRolesAsync() 方法返回一个任务并将其分配给角色,而不是该任务的实际结果。我似乎一辈子都想不通的是如何让它发挥作用。
在过去的一天里,我研究并尝试了很多方法,但都没有成功。以下是我看过的一些内容:
Is it possible to call an awaitable method in a non async method?
https://blogs.msdn.microsoft.com/pfxteam/2012/04/12/asyncawait-faq/
Calling async method in IEnumerable.Select
How to await a list of tasks asynchronously using LINQ?
how to user async/await inside a lambda
How to use async within a lambda which returns a collection
不可否认,我并不完全理解 async/await 是如何工作的,所以这可能是问题的一部分。我的 foreach 代码有效,但我希望能够理解如何使其按照我尝试的方式工作。由于我已经在这上面花了很多时间,所以我认为这将是一个很好的第一个问题。
谢谢!
编辑
我想我必须解释我在我研究的文章的每个案例中做了什么,以免将其标记为重复问题 - 我非常努力地避免这种情况 :-/。虽然问题听起来很相似,但结果却不同。对于被标记为答案的文章,我尝试了以下代码:
public async Task<ActionResult> Users()
{
var allUsers = _userManager.Users.OrderBy(x => x.FirstName);
var tasks = allUsers.Select(GetUserViewModelAsync).ToList();
return View(await Task.WhenAll(tasks));
}
public async Task<UsersViewModel> GetUserViewModelAsync(ApplicationUser user)
{
return new UsersViewModel
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
DisplayName = user.DisplayName,
Email = user.Email,
Enabled = user.Enabled,
Roles = String.Join(", ", await _userManager.GetRolesAsync(user))
};
}
我也试过像这样使用 AsEnumerable:
var usersViewModel = allUsers.AsEnumerable().Select(async user => new UsersViewModel
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
DisplayName = user.DisplayName,
Email = user.Email,
Enabled = user.Enabled,
Roles = string.Join(", ", await _userManager.GetRolesAsync(user))
}).ToList();
这两者都会产生错误消息:“InvalidOperationException:在上一个操作完成之前在此上下文中启动了第二个操作。不保证任何实例成员都是线程安全的。”
在这一点上,我原来的 ForEach 似乎是最好的选择,但我仍然想知道如果我使用异步方法执行此操作的正确方法是什么。
编辑 2 - 有答案感谢 Tseng 的评论(以及其他一些研究),我能够使用以下代码使事情正常进行:
var userViewModels = allUsers.Result.Select(async user => new UsersViewModel
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
DisplayName = user.DisplayName,
Email = user.Email,
Enabled = user.Enabled,
Roles = string.Join(", ", await _userManager.GetRolesAsync(user))
});
var vms = await Task.WhenAll(userViewModels);
return View(vms.ToList());
虽然现在我已经考虑了每个人的评论,但我开始仔细查看 SQL 事件探查器,只是为了看看数据库实际获得了多少次命中 - 正如 Matt Johnson 提到的,很多 (N+1)。
因此,虽然这确实回答了我的问题,但我现在正在重新考虑如何运行查询,并且可能只是删除主视图中的角色,并且只在每个用户被选中时拉出它们。不过,我确实通过这个问题学到了很多东西(并且学到了更多我不知道的东西),所以谢谢大家。
最佳答案
我认为你在这里混合了两种东西。表达式树和代表。 Lambda 可以用来表达它们两者,但这取决于方法接受的参数类型,它将转向哪个参数。
一个 lambda 传递给一个方法,它作为 Action<T>
或 Func<T, TResult>
将被转换为委托(delegate)(基本上是匿名函数/方法)。
当您将 lambda 表达式传递给接受 Expression<T>
的方法时,您从 lambda 创建一个表达式树。表达式树只是描述代码的代码,而不是代码本身。
也就是说,表达式树无法执行,因为它已转换为可执行代码。您可以在运行时编译表达式树,然后像委托(delegate)一样执行它。
ORM 框架使用表达式树来允许您编写可以翻译成不同内容(例如数据库查询)或在运行时动态生成代码的“代码”。
因此你不能使用 async
在接受 Expression<T>
的方法中.当您将其转换为 AsEnumerable()
时它可能起作用的原因是因为它返回一个 IEnumerable<T>
及其上的 LINQ 方法接受 Func<T, TResult>
.但它本质上是获取整个查询并在内存中执行所有操作,因此您不能使用投影(或者您必须在仅使用表达式和投影之前获取数据),将过滤后的结果转换为列表,然后对其进行过滤。
你可以尝试这样的事情:
// Filter, sort, project it into the view model type and get the data as a list
var users = await allUsers.OrderBy(user => user.FirstName)
.Select(user => new UsersViewModel
{
Id = user.Id,
UserName = user.UserName,
FirstName = user.FirstName,
LastName = user.LastName,
DisplayName = user.DisplayName,
Email = user.Email,
Enabled = user.Enabled
}).ToListAsync();
// now that we have the data, we iterate though it and
// fetch the roles
var userViewModels = users.Select(async user =>
{
user.Roles = string.Join(", ", await _userManager.GetRolesAsync(user))
});
第一部分将完全在数据库上完成,您可以保留所有优势(即顺序发生在数据库上,因此您不必在获取结果后进行内存中排序,并且 limit 调用会限制数据从数据库等获取)。
第二部分遍历内存中的结果并为每个临时模型获取数据,最后将其映射到 View 模型中。
关于c# - 在 .Select lambda 中使用 async/await,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39518163/
可以使用 lambda 和函数创建有序对(Lisp 中的缺点),如 Use of lambda for cons/car/cdr definition in SICP 所示。 它也适用于 Python
我正在尝试从另一个调用一个 AWS lambda 并执行 lambda 链接。这样做的理由是 AWS 不提供来自同一个 S3 存储桶的多个触发器。 我创建了一个带有 s3 触发器的 lambda。第一
根据以下源代码,常规 lambda 似乎可以与扩展 lambda 互换。 fun main(args: Array) { val numbers = listOf(1, 2, 3) f
A Tutorial Introduction to the Lambda Calculus 本文介绍乘法函数 The multiplication of two numbers x and y ca
我想弄清楚如何为下面的表达式绘制语法树。首先,这究竟是如何表现的?看样子是以1和2为参数,如果n是 0,它只会返回 m . 另外,有人可以指出解析树的开始,还是一个例子?我一直找不到一个。 最佳答案
在 C++0x 中,我想知道 lambda 函数的类型是什么。具体来说: #include type1 foo(int x){ return [x](int y)->int{return x * y
我在其中一个职位发布中看到了这个问题,它询问什么是 lambda 函数以及它与高阶函数的关系。我已经知道如何使用 lambda 函数,但不太自信地解释它,所以我做了一点谷歌搜索,发现了这个:What
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
Evaluate (((lambda(x y) (lambda (x) (* x y))) 5 6) 10) in Scheme. 我不知道实际上该怎么做! ((lambda (x y) (+ x x
我正在处理 MyCustomType 的实例集合如下: fun runAll(vararg commands: MyCustomType){ commands.forEach { it.myM
Brian 在他对问题 "Are side effects a good thing?" 的论证中的前提很有趣: computers are von-Neumann machines that are
在 Common Lisp 中,如果我希望两个函数共享状态,我将按如下方式执行 let over lambda: (let ((state 1)) (defun inc-state () (in
Evaluate (((lambda(x y) (lambda (x) (* x y))) 5 6) 10) in Scheme. 我不知道实际上该怎么做! ((lambda (x y) (+ x x
作为lambda calculus wiki说: There are several possible ways to define the natural numbers in lambda cal
我有一个数据类,我需要初始化一些 List .我需要获取 JsonArray 的值(我使用的是 Gson)。 我做了这个函数: private fun arrayToList(data: JsonAr
((lambda () )) 的方案中是否有简写 例如,代替 ((lambda () (define x 1) (display x))) 我希望能够做类似的事情 (empty-lam
我在 Java library 中有以下方法: public void setColumnComparator(final int columnIndex, final Comparator colu
我正在研究一个函数来计算国际象棋游戏中棋子的有效移动。 white-pawn-move 函数有效。当我试图将其概括为任一玩家的棋子 (pawn-move) 时,我遇到了非法函数调用。我已经在 repl
考虑这段代码(在 GCC 和 MSVC 上编译): int main() { auto foo = [](auto p){ typedef decltype(p) p_t;
我正在阅读一个在 lambda 内部使用 lambda 的片段,然后我想通过创建一个虚拟函数来测试它,该函数从文件中读取然后返回最大和最小数字。 这是我想出来的 dummy = lambda path
我是一名优秀的程序员,十分优秀!