我用 asp.net 身份async/await学习,我有这个问题:
我有一些IEnumerable<T> list
的功能.我使用查询语法填充此列表,如下所示:
private IEnumerable<SomeModel> GetPersons(int categoryId) {
IEnumerable<SomeModel> persons = from g in db.Categories
join c in db.Persons on g.PersonTypeId equals c.PersonTypeId
where g.CategoryId == categoryId
select new SomeModel
{
PersonName = c.FirstName + " " + c.LastName,
//....etc.
//And here I need call asynchronous function something like this:
IsAdmin = GetPermission(c.Email)
}
if (persons.Any()) {
return persons;
}
return Enumerable.Empty<SomeModel>();
}
在SomeModel中IsAdmin
为bool(当我在GetPermission中尝试Task<bool>
时,我在SomeModel中使用Task<bool>
(。GetPermission()
是这样的:
private bool GetPermission(string email) {
var user = SomeMembershipService.GetUser(email); //SomeMembershipService is Interface with Tasks and so on.
var roles = SomeMembershipService.GetRoles(user.Id); //user.Id is as string
bool result = false;
if (roles != null) {
var adm = roles.Result.FirstOrDefault(x => x.Name.Contains("Admin"));
result = adm != null;
}
return result;
}
我尝试使用异步/等待和作为任务进行写入,但我的两次尝试都是错误的。所以我认为我必须在IEnumerable<SomeModel> persons
之外调用GetPermission()
所以我将这段代码添加到 condition 之后。所以代码看起来像这样:
private IEnumerable<SomeModel> GetPersons(int categoryId) {
IEnumerable<SomeModel> persons = from g in db.Categories
join c in db.Persons on g.PersonTypeId equals c.PersonTypeId
where g.CategoryId == categoryId
select new SomeModel
{
PersonName = c.FirstName + " " + c.LastName
//....etc.
}
if (persons.Any())
{
//new code
foreach (var p in persons)
{
p.IsAdmin = GetPermission(p.Email);
}
//end of new code
return persons;
}
return Enumerable.Empty<SomeModel>();
}
但这也是错误的。也许我对 asp.net 身份和异步/等待及其使用的理解不好......你能帮我吗——我必须做什么?因为现在,GetPermission
叫得太晚了,所以应用崩溃了。当我在人员查询中调用GetPermission
时,函数也调用得太晚了(在填写人员列表之后(。我不知道如何继续。
GetUser()
一样public IUser GetUser(string username)
,GetRoles()
一样public async Task<IEnumerable<IRole>> GetRoles(string userId)
.我敢肯定,这两种方法工作正常,我在其他代码中使用它们,它们没有问题。所以我认为它必须在上面的代码中的某个地方。
很抱歉,如果这是一个愚蠢的问题,但我在这里和 msdn 上阅读了很多,但找不到结果。谢谢大家。
为什么我想使用上面的异步函数
我希望那里有函数,因为当我将整个函数作为异步任务时,调用它的另一个函数无法正常工作。
我有这个函数 - 它是 kendogrid 的数据绑定 ((:
[HttpPost]
public ActionResult _PersonsBinding([DataSourceRequest]DataSourceRequest request, int id)
{
DataSourceResult result = GetPersons(id).ToDataSourceResult(request);
return Json(result);
}
当我将函数IEnumerable<SomeModel> GetPersons
为async Task<IEnumerable<SomeModel>> GetPersons
时,绑定函数不知道 ToDataSourceResult((,当我也将这个函数设置为异步时。如果这里可能有问题,我该如何解决?请耐心等待我,我是新手...
你的问题不在于异步/等待。您的问题是因为您执行的查询不止一个。每个foreach/ToList/ToArray等将从头开始执行查询并创建新对象。因为在 linq 内部,结果是用"yield return new { .....}"生成的,并且会创建新对象。这就是为什么你在下一个foreach上丢失了IsAdmin位。(方法外(
if (persons.Any())
{
// !HERE! <- foreach. this will run the query.
foreach (var p in persons)
{
p.IsAdmin = GetPermission(p.Email);
}
//Where you foreach in it's caller.
return persons;
}
您需要先保留查询。您可以使用 ToArray((/ToList(( 修复此问题。这样,查询就是执行、迭代并存储为 Array 的查询。
private IEnumerable<SomeModel> GetPersons(int categoryId)
{
IEnumerable<SomeModel> persons = (from g in db.Categories
join c in db.Persons on g.PersonTypeId equals c.PersonTypeId
where g.CategoryId == categoryId
select new SomeModel
{
PersonName = c.FirstName + " " + c.LastName
//....etc.
}).ToArray(); // <------ here
foreach (var p in persons)
{
p.IsAdmin = GetPermission(p.Email);
}
//end of new code
return persons;
}
如果要合并GetPermission()
和查询,则应创建一个 SQL 函数。
好的,我解决了。上面的代码中没有错误,问题出在async Task<IEnumerable<IRole>> GetRoles(string userId)
.此方法工作正常,但对我上面的代码不利。
异步获取角色如下所示:
public async Task<IEnumerable<IRole>> GetRolesAsync(string userId)
{
return await IdentityManager.Roles.GetRolesForUserAsync(userId);
}
但是我不得不使用下面的代码中的获取角色。我在IMembershipService - public IEnumerable<IRole> GetRoles(string userId)
(第一个方法重命名为GetRolesAsync(中制作了新方法,如下所示:
public IEnumerable<IRole> GetRoles(string userId)
{
return AsyncHelper.RunSync(() => IdentityManager.Roles.GetRolesForUserAsync(userId));
}
这将返回常见IEnumerable<T>
。至少我可以在sql查询中使用我的函数GetPermissions。GetPermission(( 现在看起来像这样:
private bool GetPermission(string email) {
var user = SomeMembershipService.GetUser(email);
var roles = SomeMembershipService.GetRoles(user.Id);
bool result = false;
if (roles != null) {
var adm = roles.FirstOrDefault(x => x.Name.Contains("Admin"));
result = adm != null;
}
return result;
}
在sql查询中,我现在可以使用它:
....
select new SomeModel
{
PersonName = c.FirstName + " " + c.LastName,
IsAdmin = GetPermission(c.Email) // <-- This
}
....
感谢所有人,尤其是试图提供帮助的杰罗恩。