我是一个数据库优先项目。
我在VS2013中创建了一个新的MVC5站点。
我创建了一个具有电子邮件属性的applicationUser:
public class ApplicationUser : IdentityUser
{
public String EMail { get; set; }
}
然后我在AspNetUsers表中创建了一个已经创建的EMail字段。然后我创建了一个特定于域的用户存储,它继承自Microsoft.AspNet.Identity.EntityFramework.UserStore,我实现了另外两个函数: FindByEmail和FindByEmailAsync。
FindByEmail看起来像这样:
public ApplicationUser FindByEMail(String email)
{
var context = base.Context;
String commandText = "Select * from AspNetUsers Where EMail = @email";
var query = context.Database.SqlQuery(typeof(ApplicationUser), commandText,new SqlParameter("@email",email));
var result = query.ToListAsync().Result.ToArray().GetValue(0);
return result as ApplicationUser;
}
我的单元测试使用此方法运行为绿色。我现在正在尝试实现异步方法并返回一个Task。我试图这样做,而不是通过任务实现并将对象转换为ApplicationUser。我脑中的F#想要做一个Seq.Map(有趣的你 - >(ApplicationUser)你是。是否有C#的等价物?
我是否以正确的方式解决问题?我受到限制,无法遵循MSDN的示例,因为我无法执行代码优先。
答案 0 :(得分:4)
首先,对于同步版本,最好首先避免异步调用。您可以将查询编写为:
var query = context.Database.SqlQuery<ApplicationUser>(commandText, new SqlParameter("@email",email));
return query.First();
这可以避免包含“同步异步”(使用ToListAsync()
后跟Result
调用)。
对于异步版本,您只需使用:
public async Task<ApplicationUser> FindByEMailAsync(String email)
{
var context = base.Context;
String commandText = "Select * from AspNetUsers Where EMail = @email";
var query = context.Database.SqlQuery<ApplicationUser>(commandText, new SqlParameter("@email",email));
var data = await query.ToListAsync();
return data.First();
}
旁注:
我脑中的F#想要做一个Seq.Map(有趣的你 - >(ApplicationUser)你是。是否有C#的等价物?
平等的C#将通过Enumerable.Select
使用a.Select(u => (ApplicationUser)u);
。话虽如此,在这种特定情况下使用a.Cast<ApplicationUser>().First()
可能会更合适。
另一方面说明:
如果找不到电子邮件,这些方法会有问题,因为他们假设您总是会得到一个匹配的结果。您可以使用FirstOrDefaultAsync()
和FirstOrDefault()
代替First
来处理此问题,并检查空响应。我故意没有这样写,因为我试图模仿原始方法的行为(虽然你的方法会引发IndexOutOfRangeException
,但也会引发InvalidOperationException
。)